Programutveckling för Tekniska Tillämpningar Arbetsblad 4

Relevanta dokument
Programutveckling för Tekniska Tillämpningar Arbetsblad 5

Home Nerladdning typsnitt Ladda Ladda fonter Menyn Skrivare Menyn teckensnitt Menyn Verktygsfält Menyn Hjälp Snabbtangenter

Laboration 1 Introduktion till Visual Basic 6.0

Lab5 för prgmedcl04 Grafik

EnKlass. Instans 3 av EnKlass. Instans 2 av EnKlass

Språket Python - Del 2 Grundkurs i programmering med Python

3.5 Visuell programmering

Programutveckling med Java Development Kit. (JDK 1.1.x) och Programmers File Editor (PFE 7.02)

Att skriva till och läsa från terminalfönstret

Gran Canaria - Arbetsbeskrivning knapplänkar (Mediator 8)

Kort om klasser och objekt En introduktion till GUI-programmering i Java

1. Definiera klassvariabel. 2. Instansvariabel för klass. Selektera klass i Browsern och tryck på statics. Definiera protokollnamn, Protocol->Add...

6. Nu skall vi ställa in vad som skall hända när man klickar på knappen samt att markören skall ändra sig till en hand när markören är på knappen.

Labb i Datorsystemteknik och programvaruteknik Programmering av kalkylator i Visual Basic

Kodexempel från Programmering 2 Tobias Wrigstad, Ph.D.

Malmö högskola 2007/2008 Teknik och samhälle

Föreläsning 4 Programmeringsteknik DD1310. Felhantering. Syntax. try och except är reserverade ord som används för hantering av exekverings fel.

EVO DEV. EvodevExcel.GarpReportAddin

Objektorienterad Programkonstruktion. Föreläsning 3 7 nov 2016

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

Föreläsning 5-6 Innehåll

Paneler - VCPXX.2. Programmeringsmanual för VCP-paneler. Revision 2

Administrativt. Programmeringsteknik för I1. Dagens program. Objektorienterad programmering

Här beskrivs Eclipse, den programutvecklingsmiljö som utnyttjas i programmeringskurserna. Mera information finns på:

OEvent Manual. Version 1.2. ÅID-orientering

5. En metod som anropar sig själv a) får inte förekomma i Java-program b) kallas destruktiv c) kallas iterativ d) kallas rekursiv 6. Vilka värden har

KARLSTADS UNIVERSITET 12/8/09 informatik & datavetenskap Johan Öfverberg, Kerstin Andersson Laboration 4, ISG A04 och DVG A08 HT-09

Laboration: Whitebox- och blackboxtesting

Användarhandledning Version 1.2

Föreläsning 8 Programmeringsteknik och Matlab DD1312. Klassmetod. Egen modul

Datorövning 1 Statistik med Excel (Office 2010, svenska)

3.0. Tips och Trix Sida 1 av 18

Övning 6. Ali Tofigh 24 Oktober, 2006

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

4.4 Swing ett interaktivt grafiskt gränssnitt

Tentamen i Introduktion till programmering

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Föreläsning 3-4 Innehåll

Uppgift 18 Eget programval

Inledande programmering med C# (1DV402) Ditt första C#-program med Visual Studio

Klasser och objekt, referenser Grundkurs i programmering med Python

729G04 Programmering och diskret matematik. Föreläsning 7

Föreläsning 5 (6) Metoder. Metoder Deklarera. Metoder. Parametrar Returvärden Överlagring Konstruktorer Statiska metoder tostring() metoden javadoc

Sätt att skriva ut binärträd

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

Objektorienterad programmering Föreläsning 2

Windows Forms Winstrand Development

Mirasys Användarguide: Live Sök Export. November Bygger på delar ur dokumentet Mirasys NVR 5.10 Användarvägledning Mirasys, Ltd.

Labora&on 2 Funk&oner, if och loop övningar/uppgi:er

FÖRSLAG TILL LÖSNINGAR FÖR TENTAMEN I INTERNETPROGRAMMERING MED JAVA, 5p för SY , kl

Klasser i Java kan ha metoder och egenskaper. Metoder beskriver funktioner som klassen kan utföra. Egenskaper beskriver innehållet i klassen.

Komponenter med COM (och COM+/VC++ 7.0)

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

F6 Objektorienterad design. ID1004 Objektorienterad programmering Fredrik Kilander

Microsoft Excel. Avancerade funktioner

Problemlösning och funktioner Grundkurs i programmering med Python

Högskolan Dalarna sid 1 av 7 DI-institutionen Hans-Edy Mårtensson Sten Sundin

Microsoft Word. Lathund för. Innehåll. Autokorrigering. Autotext. Format

Introduktion till Matlab

Objektorienterad Programkonstruktion. Föreläsning 3 9 nov 2015

Hos vad? och bör därför vara instanseller klassvariabel i vilken klass?

Arbeta med databas. Översikt. Lektion 1: Arbeta med Entity Data Models. Arbeta med Entity Data Models. LINQ (Language Integrated Query).

Datorövning 1. int sgd(int m, int n) { int rest; while ( n!= 0 ) { rest = m % n; m = n; n = rest; return m;

DAT043 - Föreläsning 7

Migrera till Access 2010

FactoryCast HMI. Premium & Quantum PLC. Applets

Laboration 3 GUI-programmering

In- och utenheter. Händelsebaserad programmering i GLUT. Interrupt-baserad interaktion. Sampling / polling. Händelsebaserad interaktion (forts.

Att prova på en enkel Applet och att lära sig olika sätt att hämta data från tangentbordet. Du får även prova på att skapa din första riktiga klass.

Laboration: Grunderna i MATLAB

Objektorienterad programmering i Java I. Uppgifter: 2 Beräknad tid: 5-8 timmar (OBS! Endast ett labbtillfälle) Att läsa: kapitel 5 6

Bilaga 2. Layoutstöd för examensarbeten och uppsatser

Skolan för Datavetenskap och kommunikation PROGRAMMERINGSTEKNIK FÖRELÄSNING 15

Handbok KXSLDbg. Keith Isdale Översättare: Stefan Asserhäll

Det är principer och idéer som är viktiga. Skriv så att du övertygar examinatorn om att du har förstått dessa även om detaljer kan vara felaktiga.

Handbok Kig. Dominique Devriese Översättare: Stefan Asserhäll

Introduktion till Matlab

Övningar i JavaScript del 3

Frekvenstabell över tärningskast med C#

ID1004 Laboration 3, 5-6 November 2012

ALEPH ver. 16 Introduktion

2 Eclipse en handledning

Pampas Arbetsbeskrivning gif-animering (Mediator 8)

Överlagring, static, testning, formella metoder och undantag! Förelasning 13!! TDA540 Objektorienterad Programmering!

Calligra. En allmän inledning. Raphael Langerhorst Jost Schenck Översättare: Stefan Asserhäll

JAVA Mer om klasser och objektorientering

Exemple på Tentauppgifter Webbprogrammering

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

Introduktion. Klasser. TDP004 Objektorienterad Programmering Fö 2 Objektorientering grunder

Datorövning 1 Statistik med Excel (Office 2007, svenska)

Enkla variabler kontra referensvariabel

Hjälp för Timmerweb Mobil 3

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Idag: Centrerad utskrift. Granskning. DD1311 Programmeringsteknik med PBL. Granskning Felhantering GUI. Föreläsning 15.

4 Kolumn Kalkylbladet är uppdelat i rader (horisontellt) och kolumner (vertikalt). Där dessa möts finns alltid en cell.

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

SMART Ink 3.0 ANVÄNDARHANDBOK FÖR MAC OS X-OPERATIVSYSTEM

Så här skriver du ditt första program i C++

Grafiska användargränssnitt i Java

Tentamen i TDP004 Objektorienterad Programmering Praktisk del

Transkript:

Programutveckling för Tekniska Tillämpningar Arbetsblad 4 I detta arbetsblad innehåller följande moment: 1. Skapa en wxpython applikation med huvudfönster och rapportfönster. 2. Integrering av beräkningskod i användargränssnitt. 3. Uppritning av geometri, elementnät och elementflöden. Skapa en wxpython applikation i wxglade Starta wxglade. Marker Application i trädvyn. I egenskapsfönstret sätts Name till applikationens namn. Namnge på samma sätt applikationens klass i rutan Class. För att programmet skall bli lättare att underhålla är det bra om varje klass i wxglade genereras som separata filer. Detta sätts i rutan Code Generation genom att välja Separate file for each class. Det sista vi gör för applikationsklassen är att ange var de genererade filerna skall placeras. Detta anges i rutan Output path. Vi har nu definierat applikationsklassen och de övergripande inställningarna i wxglade. I nästa steg skall vi definiera huvudfönstret för programmet. Huvudfönster Huvudfönstret är programmets centralpunkt. Det är från detta fönster som flödet i programmet styrs och underfönster öppnas. En klass för huvudfönstret skapas genom att välja en wx.frame i verktygslådan. Figur 1 Skapa en wx.frame för huvudfönster En dialogruta visas där wxglade frågar efter vilken typ av Frame klass som skall skapas. Ange wxframe och ge klassen namnet mainwindow. I nästa steg skall vi sätta en del standardvärden för fönstret i egenskapsmenyn. Under Common fliken sätt följande egenskaper: Egenskap Värde Name mainwindow Size 640, 480

Under fliken Widget anges applikationens titel i rutan Title. Denna titel kommer att visas längst upp i fönstret. Kryssa sedan för Has menubar. Nu skapas en MenuBar instans som i sin tur kopplas till huvudfönstret. I egenskapsfönstret sätts namnet på meny instansen till mainmenu. Klicka sedan på "Edit menus..." för att skapa meny strukturen. Ange följande struktur: När strukturen är klar väljs OK. Figur 2 Menystruktur I nästa steg skall vi skapa ett verktygsfält. Klicka på mainwindow i trädvyn. Under fliken Widget i egenskapsfönstret markeras alternativet Has ToolBar. Ange namnet på det skapade verktygsfältet till maintoolbar. Bilderna till verktygsfältet har storleken 22x22 varför egenskapen Bitmapsize sätts till 22, 22. Egenskaperna wxtb_flat, wxtb_text skall också markeras. Klicka därefter på Edit tools och skapa på samma sätt som för menyraden följande struktur:

Figur 3 Struktur för verktygsfält (maintoolbar) Generering av programkod Innan vi kan gå vidare och integrera beräkningskoden måste wxglade generera källkod för det skapade gränssnittet. Innan kodgenereringen kan påbörjas måste indata i wxglade sparas. Detta görs genom att välja File/Save i menyn i verktygsfältet för wxglade. I nästa steg markeras instansen Application i trädvyn. Under Application fliken i egenskapsfönstret sätts egenskapen Top window till det just skapade huvudfönstret. Om allt fungerat kan koden genereras genom att klicka på knappen Generate code. Nu skall det finnas två Python filer i målkatalogen, en för applikationsklassen och en för själva huvudfönstret. Integrering av beräkningskod i användargränssnittet Lägg till följande i början av MainWindow.py: # * coding: utf 8 * # generated by wxglade 0.6.3 on Sun Apr 19 16:39:24 2009 import wx from model import * # begin wxglade: dependencies För att hantera programmets initiering skapar vi en egen initieringsmetod _initapp(). Metoden placeras efter de av wxglade genererade metoderna set_properties och do_layout(). def _initapp(self): Initiera program variabler. # Skapa en instans av datamodellen

self._model = FlowModel() Metoden anropas sist i MainWindow klassens init () metod. def init (self, *args, **kwds): # begin wxglade: MainWindow. init kwds["style"] = wx.default_frame_style wx.frame. init (self, *args, **kwds) # < bortklippt kod > self.bind(wx.evt_tool, self.oncalcstart, id=5) # end wxglade self._initapp() Var noga med att inte ändra kod mellan de speciella taggar som wxglade skapar (# begin wxglade, # end wxglade) Modellhantering (Ny, Öppna och Spara) För att kunna hantera öppna och spara modeller i programmet uppdateras vår modellklass med en variabel, filename, som skall lagra modellens aktuella filnamn. Variabeln läggs till i klassens konstruktor. class FlowModel: def init (self): self.filename = "" self.createinput() Eftersom vi nu lagrar vilket filnamn som modellen användare modifierar vi också metoden read FromFile som skapades i förra arbetsbladet. Nu anges parametern till denna metod med standardvärdet, filename=, vilket medför att vi kan utelämna denna parameter vid anrop och istället använda den inbyggda variabeln, self.filename, för att ange från vilken fil indata skall läsas. def readfromfile(self, filename=""): if filename!= "": self.filename = filename inputfile = open(self.filename, 'r') Vi skall nu koppla kod till händelsemetoderna skapade tidigare. Metoden onnew() används för att skapa en ny modell. Detta görs enkelt genom att skapa en ny instans och tilldela denna till klassvariabeln self._model. def onnew(self, event): # wxglade: MainWindow.<event_handler> self._model = FlowModel() För att öppna en fil behöver vi visa en standard fildialogruta där användaren kan välja en fil som skall läsas in. wxpython innehåller en sådan klass wx.fileselector. Nedan visas hur metoden onopen() implementerats med hjälp av denna. def onopen(self, event): # wxglade: MainWindow.<event_handler>

Menyhändelse för att spara öppna en modell. self._model.filename = wx.fileselector( "Open file", default_extension="*.flw", wildcard="*.flw", flags=wx.fd_open) if self._model.filename!="": self._model.readfromfile() Om användare avbryter dialogrutan returnerar metoden en tom sträng. Parametern flags=wx.fd_open anger att dialogfönstret skall användas för att välja en existerande fil som skall öppnas. Motsvarande flagga för en dialogruta som uppmanar om filnamn för att spara är flags=wx.fd_save. Skapa på motsvarande sätt händelsemetoderna onsave() och onsaveas(). Skapa en tom metod, savetofile(), i modellklassen för att spara modellen till fil (Denna implementeras i nästa arbetsblad). Exekvering av beräkning Beräkningen skall utföras när menyn Beräkning/Starta eller knappen Beräkna väljs. Metoden som är kopplad till dessa metoder är definierad i oncalcstart(). I denna metod skall koden för exekvering av beräkningen flyttas, dvs den kod som i arbetsblad 3 låg i huvudprogrammet för model.py. En flagga läggas till i modellklassen, som sätts till True när en modell har lästs in från fil. Använd denna flagga i oncalcstart() för att se till att beräkningen inte exekveras utan inlästa data. Fönster för resultatrapport Klicka på Application Skapa en wxframe med klassnamnet ReportWindow Flik Common Ange namnet till reportwindow Sätt Size till 700,500 Flik Widget Sätt Title = Report Window Lägg till en TextCtrl Flik Common Sätt namn till reporttext Sätt Font till Courier New/Consolas 11 Flik Layout

Sätt proportion till 1 Sätt wxexpand Flik Widget Sätt wxte_multiline, wxte_rich2, wxte_readonly Trädvyn. Klicka på Application. Spara. Välj Generate code. För att kunna använda fönsterklassen, ReportWindow, måste modulen för denna importeras från MainWindow.py. # * coding: utf 8 * # generated by wxglade 0.6.3 on Sun Apr 19 16:39:24 2009 import wx from model import * from ReportWindow import * För att kunna använda den nya klassen måste denna instantieras. Detta görs lämpligtvis i onshow Report() metoden. Ett fönster i wxpython visas inte bara för att en instans av det skapats, utan metoden Show() måste anropas för att visa det på skärmen. Koden blir då: def onshowreport(self, event): # wxglade: MainWindow.<event_handler> self._reportwindow = ReportWindow(self, 1) self._reportwindow.show() För att kunna presentera en resultatrapport måste metoden createreport() i model.py modifieras så att all utdata skrivs till en fil istället för till skärmen. En klassvariabel läggs också till i modellklassen för att lagra filnamnet till den genererade rapporten. print kommandot är inte tillgängligt för att skriva till fil utan write() metoden för filklassen används istället. Följande exempel visar hur data kan skrivas till fil. def createreport(self): reportfile = open(self.reportfilename, "w") reportfile.write("element koordinater\n\n") reportfile.write( "%5s %10s %10s %10s %10s %10s %10s\n" % ("Elnr", "x1(m)", "x2(m)", "x3(m)", "y1(m)", "y2(m)", "y3(m)") ) i = 1 for elx, ely in zip(self._ex, self._ey): reportfile.write( "%05d %10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n" % (i, elx[0], elx[1], elx[2], ely[0], ely[1], ely[2]) ) i+=1 Lägg märke till att \n används för att göra radbrytningar i utskrifter när write() metoden används.

Uppritning av geometri När programmet läst in indata skall geometrin visas i huvudfönstret. För att kunna implementera uppritningen av detta måste en wxpanel kontroll läggas till huvudfönstret. Välj sizer1 i trädvyn och ändra namnet till mainsizer. En sizer är en kontroll som själv innehåller andra kontroller. Klicka på wxpanel kontrollen i verktygslådan. Figur 4 wxpanel kontroll Klicka sedan på det streckade området i huvudfönstret för att placera kontrollen. Ge kontrollen namnet mainpanel (i property fönstret). Sätt också bakgrundsfärgen till vit genom att ange egenskapen Background = #ffffff. Om allt fungerat skall fönstret se ut som i följande figur: Figur 5 Fönster med wxpanel För att kunna rita på mainpanel måste först två stycken händelsemetoder skapas och knytas till händelser. Uppritningen skall ske i metoden onpaint(). Metoden har som parameter variabeln event. wxpython fyller denna variabel med information om den aktuella händelsen. def onpaint(self, event): Uppritningshändelse för fönster. dc = wx.paintdc(self.mainpanel) gc = wx.graphicscontext.create(dc) # Rita linjer gc.setpen(wx.pen('blue',1))

gc.strokeline(20,20,150,150) # Rita punkter gc.setpen(wx.nullpen) gc.setbrush(wx.brush('red')) gc.setfont(self._font) gc.drawellipse(50, 50, 20, 20) gc.drawtext(u"det är kul att rita i wxpython", 50, 50) För att metoden skall utföra uppritning måste den kopplas till en händelse. Detta görs med metoden Bind() för kontrollen mainpanel i metoden _oninitapp(). På samma gång skapas också klassvariablen self._font som behövs för uppritningen in onpaint(). # Skapa en font för att rita med self._font = wx.font(10, wx.swiss, wx.normal, wx.bold, False, "Arial") # Koppla uppritning och omskalningshändelser till metoder. self.mainpanel.bind(wx.evt_paint, self.onpaint) För att kunna skala om uppritningen i fönstret då detta ändrar storlek måste ytterligare en händelsemetod skapas och kopplas, onsize(). Denna metod kommer att anropas varje gång fönstret ändrar storlek. Storleken på det uppdaterade fönstret kan hämtas med metoden GetSize() i event variabeln. def onsize(self, event): Storleksändringshändelse för fönster. self._width, self._height = event.getsize() På samma sätt som för onpaint() metoden kopplas händelsemetoden, onsize(), till händelsen med hjälp av Bind() metoden för mainpanel instansen. # Koppla uppritning och omskalningshändelser till metoder. self.mainpanel.bind(wx.evt_paint, self.onpaint) self.mainpanel.bind(wx.evt_size, self.onsize) Nu finns metoderna på plats för att implementera uppritningen av geometri och elementnät. För att rita upp elementnät kan det var bra att Koordinattransformation För att objektet skall ritas upp i lämplig storlek måste en skalning göras. Detta går till så att man bestämmer lägsta och högsta värdet på koordinaterna och till detta lägger en marginal på exempelvis 10% av objektets storlek. På detta sätt bestämmer man x min, y min, x max och y max. Utifrån dessa värden bestämmer man skalfaktor s och translation x 0 och y 0 enligt

k Width xmax xmin s = min k Height ymax ymin 1 k x0 = s xmin + Width 2 1 k y0 = Height s ymin Height 2 Koordinater för uppritning kan då bestämmas enligt x y s s = x 0 = y 0 + s x s y Följande figur visar hur koordinatsystemet är definierat i en wxpanel kontroll samt det nya koordinatsystemet för uppritning. y (0,0) (0,width) x s Canvas k * height height (x 0, y 0 ) x (0,height ) (height, widt h) k * width width y s Figur 6 Koordinatsystem i wxpanel kontroll För att hantera koodinattransformationen implementeras en metod, calcscaling(), i MainWindow för beräkning av skalfaktorerna. Variablerna self.width och self.height läggs till init metoden i MainWindow. Variablerna kommer att innehålla stoleken på fönstret. def _initapp(self): # < bortklippt kod > # Koppla uppritning och omskalningshändelser till metoder.

self._width, self._height = self.mainpanel.getsize() self.mainpanel.bind(wx.evt_paint, self.onpaint) self.mainpanel.bind(wx.evt_size, self.onsize) def calcscaling(self): Beräkna skalfaktorer för uppritning. limits = self._flowmodel.limits self._k = 0.8 # < bortklippt kod > self._x0 =... self._y0 =... För att förenkla hanteringen av koordinattransformationerna kan det vara lämpligt att implementera en metod som konverterar från verkliga koordinater till skärmkoordinater. Denna kan ha följande principiella utseende (Implementerad i MainWindow): def worldtoscreen(self, x, y): return ( {skärmkoordinat x}, {skärmkoordinat y}) Där {skärmkoodinat x} och {skärmkoodinat x} ersätts med beräkningar för skärmkoordinater. Skalfaktorerna beräknade tidigare är beroende av storleken på fönstret. Eftersom fönstrets storlek kan ändras av användaren måste detta också hanteras av programmet. Vi har tidigare implementerat metoden onsize() och nu utökas denna metod med ett anrop till calcscaling(). Uppritning def onsize(self, event): Storleksändringshändelse för fönster. self._width, self._height = event.getsize() self.calcscaling() Eftersom programmet skall kunna rita upp ett antal olika saker skapas en variabel self._drawmode, samt ett antal konstanter som anger olika typer av uppritning. Denna anger vilken typ av uppritning som skall göras. När programmet startas är self._drawmode satt till self.dm_none för att ingen uppritning skall göras. def _initapp(self): Initiera program variabler. # < borklippt kod > # Uppritningsvariabler self._width, self._height = self.mainpanel.getsize() self.dm_geometry = 0 self.dm_mesh = 1

self.dm_flow = 2 self.dm_scalar = 3 self.dm_none = 1 self._drawmode = self.dm_geometry # Koppla uppritning och omskalningshändelser till metoder. self.mainpanel.bind(wx.evt_paint, self.onpaint) self.mainpanel.bind(wx.evt_size, self.onsize) Uppritningen i formuläret implementeras lämpligen i metoden, onpaint(), i MainWindow. def onpaint(self, event): Uppritningshändelse för fönster. dc = wx.paintdc(self.mainpanel) gc = wx.graphicscontext.create(dc) self.calcscaling() if self._drawmode == self.dm_geometry: self.drawgeometry(gc) if self._drawmode == self.dm_mesh: self.drawmesh(gc) if self._drawmode == self.dm_flow: self.drawmesh(gc) self.drawflow(gc) För att inte överlasta onpaint() metoden med kod delas denna upp i fler metoder för uppritning. Lägg märke till att GraphicsContext variabeln, gc, skickas med anropen till de olika metoderna. Detta medför att metoderna för uppritning inte bara kan användas för uppritning till skärmen utan också kan användas för att göra uppritning till skrivare. Implementera metoder för uppritning av geometri, elementnät och elementflöde (huvudspänningar för plan spänning) Redovisning Redovisningen av uppgiften skall innehålla: Programlista Beskrivning av indataformat Skärmdumpar (Alt+Print Screen)