Windows Forms Radiobutton als globale Variable in neue Form

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
AndrejStudent
User
Beiträge: 5
Registriert: Mittwoch 25. März 2015, 11:15

Hallo,
leider bin ich noch ein ziemlicher Anfänger, was das Programmieren mit Python angeht und würde mich über eure Hilfe sehr freuen.

Zu meinem Problem:
Ich habe eine Klasse (FensterParameter) erstellt, die eine Benutzerabfrage mit Radiobuttons darstellt. Wählt man ein Radiobutton an und klickt auf den Button Weiter, so öffnet sich ein zweites Fenster (FensterParameterauswahl). Hier möchte ich den Text des in der Klasse (FensterParameter) gewählten Radiobuttons anzeigen lassen. Mein Code bisher:

Code: Alles auswählen

class FensterParameter(Form):
        def __init__(self):	
				self.Text = "Schraubenparameter"
				self.Width = 500
				self.Height = 300

				self.label1 = Label()
				self.label1.Text = "Treffen Sie folgende Auswahl:"
				self.label1.Location = Point(50, 50)
				self.label1.AutoSize = True
				
				self.radio1 = RadioButton()
				self.radio1.Text = "Festigkeit"
				self.radio1.Location = Point(75, 100)
				self.radio1.Checked = False
				
				self.radio2 = RadioButton()
				self.radio2.Text = "Durchmesser"
				self.radio2.Location = Point(75, 150)
				self.radio2.Checked = False

				self.radio3 = RadioButton()
				self.radio3.Text = "Anzahl Schrauben"
				self.radio3.Location = Point(75, 200)
				self.radio3.Checked = False

				self.button1 = Button()
				self.button1.Text = "Weiter"
				self.button1.Location = Point (400, 200)
				self.button1.Click += self.button1Pressed

				self.AcceptButton = self.button1

				self.Controls.Add(self.button1)
				self.Controls.Add(self.label1)
				self.Controls.Add(self.radio1)
				self.Controls.Add(self.radio2)
				self.Controls.Add(self.radio3)
				
				global radio1
				global radio2
				global radio3
				radio1 =  self.radio1
				radio2 = self.radio2
				radio3 = self.radio3
				
        def button1Pressed(self, sender, args):
            
				third_form = FensterParameterAuswahl()
				third_form.Show()
				
class FensterParameterAuswahl(Form):
		def __init__(self):
				self.Text = "Parameterauswahl"
				self.Width = 500
				self.Height = 300
				
				if radio1 == True:
				
					self.label1 = Label()
					self.label1.Text = "Festigkeit"
					self.label1.Location = Point(50,50)
					self.label1.AutoSize = True
					
					self.Controls.Add(self.label1)
					
				elif radio2 == True:
				
					self.label2 = Label()
					self.label2.Text = "Durchmesser"
					self.label2.Location = Point(50,50)
					self.label2.AutoSize = True
					
					self.Controls.Add(self.label2)
					
				elif radio3 == True:
				
					self.label3 = Label()
					self.label3.Text = "Anzahl Schrauben"
					self.label3.Location = Point(50,50)
					self.label3.AutoSize = True
					
					self.Controls.Add(self.label3)
					
				else:
				
					self.label4 = Label()
					self.label4.Text = "Es wurde keine Auswahl getroffen!"
					self.label4.Location = Point(50, 50)
					self.label4.AutoSize = True
					
					self.Controls.Add(self.label4)
Freue mich über eine detaillierte Lösung, da ich als Anfänger noch recht schlechtes Verständnis habe. Dankeschön!
Zuletzt geändert von Anonymous am Mittwoch 25. März 2015, 11:32, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@AndrejStudent: Globale Variable ist das Stichwort: Das will man nicht! Vergiss das es das Schlüsselwort ``global`` in Python gibt.

Ermittle den aktivierten Radiobutton nachdem der Benutzer auf die Schaltfläche geklickt hat und bevor Du das neue Fenster anzeigst. Diesem Fenster kannst Du den Text beim Erstellen des Objekts als Argument mitgeben. Wo der herkommt braucht der Code in dem neuen Fenster doch gar nicht zu wissen.

Muss man nicht auch irgendwie festlegen welche Radiobuttons zusammen eine ”Gruppe” bilden?

Das `RadioButton`-Objekt mit `True` oder `False` zu vergleichen wird ziemlich sicher nicht das gewünschte Ergebnis bringen, denn diese `RadioButton`-Objekte sind ja vom Typ `RadioButton` und nicht vom Typ `bool` wie `True` und `False`, also wird der Vergleich immer `False` ergeben, egal ob man nun mit `True` oder mit `False` vergleicht. Wahrscheinlich muss man das `Checked`-Attribut anschauen. Und das kann man dann auch *direkt* verwenden, denn das ist ja schon `True` oder `False` und durch ein ``wahrheitswert == True`` bekommt nur wieder genau den Wert heraus den `wahrheitswert` sowieso schon hatte.

Namen sollen dem Leser vermitteln was ein Wert im Kontext des Programms bedeutet. Irgendwelche supergenerischen Namen wie `label` oder `radio` tun das nicht. Die Frage ist doch was bedeutet das Label oder der jeweilige Radiobutton.

Durchnummerieren sollte man Namen auch nicht. Das passiert entweder wenn man sich keine sinnvollen Namen überlegt (hier bei `label` und `button` der Fall) oder man möchte eigentlich nur *einen* Namen für eine Datenstruktur haben. Sehr häufig ist das eine Liste. Das betrifft hier die Radiobuttons. Das würde man die Namen zum Beispiel in einer Liste definieren und dann in einer Schleife eine Liste mit `RadioButton`-Objekten erzeugen. Die kann man dann zum Testen auch wieder in einer Schleife durchgehen bis man das vom Benutzer Ausgewählte findet.

Da alle drei mit `False` initialiert werden muss der Code übrigens auch damit umgehen können wenn der Benutzer die 'Weiter'-Schaltfläche drückt ohne vorher eine Auswahlt getroffen zu haben!

Es macht keinen Sinn grundsätzlich alles an das Objekt zu binden. Da gehören nur Attribute hin, die den Zustand des Objekts ausmachen und auf die man deshalb später in anderen Methoden noch zugreifen muss.

Das zweite Fenster besteht fast nur aus Quelltextwiederholungen die sich ganz minimal unterscheiden. Das verletzt das „Don't Reapeat Yourself”- oder DRY-Prinzip. Das ist eine ziemlich Grundlegende Sache beim Programmieren das man soweit wie möglich versucht Redundanzen zu vermeiden. Das führt zu fehleranfälligem, schlecht wartbarem Quelltext. Es wird dort letztendlich im Programmablauf nur *ein* Label angezeigt — trotzdem steht der Quelltext dafür *vier* mal in der Methode statt *ein* mal. Die Zweige unterscheiden sich ja nur dadurch *was* auf dem `Label` geschrieben steht, also muss man auch nur diese Entscheidung in verschiedene Zweige stecken und *danach* *einmal* das Ergebnis in einem `Label` anzeigen.

Was die Quelltextformatierung angeht könntest Du mal einen Blick in den Style Guide for Python Code werfen. Einrückung ist zum Beispiel per Konvention vier Leerzeichen pro Ebene.
BlackJack

Mal als lauffähiges Beispiel:

Code: Alles auswählen

#!/usr/bin/env ipy.exe
# coding: utf8
import clr
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')

from System.Drawing import Point
from System.Windows.Forms import Application, Button, Form, Label, RadioButton


class ChosenParameterForm(Form):

    def __init__(self, parameter):
        Form.__init__(self)
        self.Text = 'Parameterauswahl'
        self.Width = 500
        self.Height = 300

        if parameter is None:
            parameter = 'Es wurde keine Auswahl getroffen!'

        label = Label()
        label.Text = parameter
        label.Location = Point(50, 50)
        label.AutoSize = True

        self.Controls.Add(label)


class ScrewParameterForm(Form):

    def __init__(self):
        Form.__init__(self)
        self.Text = 'Schraubenparameter'
        self.Width = 500
        self.Height = 300

        label = Label()
        label.Text = 'Treffen Sie folgende Auswahl:'
        label.Location = Point(50, 50)
        label.AutoSize = True
        self.Controls.Add(label)

        self.parameter_radios = list()
        for i, text in enumerate(
            ['Festigkeit', 'Durchmesser', 'Anzahl Schrauben']
        ):
            radio = RadioButton()
            radio.Text = text
            radio.Location = Point(75, 100 + i * 50)
            radio.Checked = False
            self.parameter_radios.append(radio)
            self.Controls.Add(radio)

        button = Button()
        button.Text = 'Weiter'
        button.Location = Point (400, 200)
        button.Click += self.on_next
        self.AcceptButton = button
        self.Controls.Add(button)

    def on_next(self, _sender, _args):
        for radio in self.parameter_radios:
            if radio.Checked:
                parameter = radio.Text
                break
        else:
            parameter = None

        ChosenParameterForm(parameter).Show()


def main():
    form = ScrewParameterForm()
    Application.Run(form)


if __name__ == '__main__':
    main()
Wobei hier unschön ist das die Datenhaltung in Anzeigeelementen passiert, eigentlich würde man erst einmal die Geschäftslogik des Programms ohne grafische Oberfläche umsetzen.
AndrejStudent
User
Beiträge: 5
Registriert: Mittwoch 25. März 2015, 11:15

Vielen Dank für die Antworten. Habe das Problem gelöst, zwar immer noch ohne die Schleifen, aber die obigen Tipps konnte ich umsetzen.

Viele Grüße
Andreas
BlackJack

Ich habe in einem Nachbarthema gerade gelernt das `Windows.Forms` auch Layout-Manager kennt. Die sollte man dann natürlich auch verwenden statt alles pixelgenau manuell zu positionieren.
Antworten