Wie eigene Widgets erstellen?

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Hand
User
Beiträge: 65
Registriert: Sonntag 28. Januar 2007, 14:28

Hätt da gleich nochmal ne Frage, wie erstellt man eigene Widgets wie z.B. einen Button wie bei Labview

http://www.neatware.com/myrmecox/media/ ... freq-1.jpg

nimmt man als Grundlage ein wx.Image und tauscht bei einem Klick einfach das Image aus oder gibts da noch andere Tricks?
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hand hat geschrieben:eigene Widgets wie z.B. einen Button
Hallo Hand!

Wenn du wirklich die Buttons und nicht die Drehregler meinst, dann ist es ziemlich einfach.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import wx
from wx.lib.buttons import ThemedGenBitmapButton

wx.SetDefaultPyEncoding("iso-8859-1")


class MyFrame(wx.Frame):
    
    def __init__(
        self, parent = None, id = -1, title = "Example", size = wx.Size(550, 420)
    ):
        
        wx.Frame.__init__(self, parent, id, title, size = size)
        
        panel = wx.Panel(self)
        
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox_main)
        
        # Button mit Bild
        bmp = wx.ArtProvider_GetBitmap(wx.ART_CDROM, wx.ART_BUTTON)
        btn = ThemedGenBitmapButton(panel, -1, bmp, size = (50, 50))
        self.btn = btn
        vbox_main.Add(btn, 0, wx.ALIGN_CENTER | wx.ALL, 50)
        btn.Bind(wx.EVT_BUTTON, self.change_bmp)
        
        self.bmp_flag = 0
    
    
    def change_bmp(self, event):
        
        if self.bmp_flag == 0:
            bmp = wx.ArtProvider_GetBitmap(wx.ART_DELETE, wx.ART_BUTTON)
            self.bmp_flag = 1
        else:
            bmp = wx.ArtProvider_GetBitmap(wx.ART_CDROM, wx.ART_BUTTON)
            self.bmp_flag = 0
        self.btn.SetBitmapLabel(bmp)


def main():
    """Testing"""
    
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

...
Ansonsten gibt es immer die Möglichkeit, etwas selbst zu zeichnen. Du kannst z.B. auf ein ``wx.Window`` zeichnen, wenn keine weiteren Widgets in diesem Widget angezeigt werden sollen.
Du kannst auf ein ``wx.Panel`` zeichnen, wenn innerhalb des neuen Widgets noch andere Widgets angezeigt werden sollen.

Dafür solltest du dich mit den Zeichenfunktionen von wxPython befassen. Jedes Widget hat einen Device Context (=DC). Diesen kannst du dir holen und darauf zeichnen.
Hier ist ein kleines Beispiel: http://www.python-forum.de/post-54147.html#54147

Den Drehregler würde ich in einem Grafikprogramm zeichnen und von wxPython anzeigen lassen. --> mit ``BufferedPaintDC``.

Die Texte würde ich in einer Liste (z.B. ["2", "4", "6", "8", "10"]) definieren und mit ``DrawText()`` auf den DC zeichnen. Natürlich solltest du dir Gedanken darüber machen, wie du die Texte exakt am Kreis ausrichtest, aber das ist reine Mathematik. Die Teilstriche kannst du mit ``DrawLine()`` zeichnen.

Diese Ereignisse könnten noch interessant sein, um die Mausposition abzufangen und zu prüfen, ob die Maustaste gedrückt ist, oder nicht.
- wx.EVT_ENTER_WINDOW
- wx.EVT_LEAVE_WINDOW
- wx.EVT_MOTION ?
- wx.EVT_LEFT_DOWN

``event.LeftIsDown()`` sollte dir zurück geben, ob die linke Maustaste gedrückt ist.

``event.GetPosition()`` oder ``event.GetX()`` und ``event.GetY()`` sollten dir die aktuelle Mausposition verraten. -- Abhängig davon, in welchem EventHandler die Methoden aufgerufen werden.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hi Hand!

Wenn du dir die Quellcodes der Widgets von Andrea Gavana ansiehst, dann erfährst du ziemlich gut, wie man eigene Widgets für wxPython erstellen kann.

http://xoomer.alice.it/infinity77/eng/freeware.html

Besonders dieses Widget könnte interessant für dich sein: http://xoomer.alice.it/infinity77/eng/KnobCtrl.html

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Hand
User
Beiträge: 65
Registriert: Sonntag 28. Januar 2007, 14:28

hallo, mittlerweile habe ich mein erstes Widget gemacht.
Wie empfohlen auf Basis von wx.Panel :wink:

Code: Alles auswählen

class myControl(wx.Panel):
    def __init__(self, parent, pos, size):
        wx.Panel.__init__(self, parent, -1, pos,size)
        self.size = size
        self.SetBackgroundColour(wx.Colour(179,179,179))
        text = wx.TextCtrl(self, -1, '', (4,4), (self.size[0]-8,self.size[1]-8), style=wx.NO_BORDER)
        text.SetBackgroundColour(wx.Colour(210,210,210))
        self.Bind(wx.EVT_PAINT, self._on_paint)

    def _on_paint(self, evt):
        dc = wx.PaintDC(self)
        for i in range(4):
            if(i == 0): dc.SetPen(wx.Pen(wx.Colour(164,164,164)))
            if(i == 1): dc.SetPen(wx.Pen(wx.Colour(147,147,147)))
            if(i == 2): dc.SetPen(wx.Pen(wx.Colour(136,136,136)))
            if(i == 3): dc.SetPen(wx.Pen(wx.Colour(130,130,130)))
            dc.DrawLine(i,i,self.size[0]-i,i)
            dc.DrawLine(i,i,i,self.size[1]-(i+1))
            if(i == 0): dc.SetPen(wx.Pen(wx.Colour(191,191,191)))
            if(i == 1): dc.SetPen(wx.Pen(wx.Colour(195,195,195)))
            if(i == 2): dc.SetPen(wx.Pen(wx.Colour(190,190,190)))
            if(i == 3): dc.SetPen(wx.Pen(wx.Colour(187,187,187)))
            dc.DrawLine(self.size[0]-i,self.size[1]-i,i,self.size[1]-i)
            dc.DrawLine(self.size[0]-i,self.size[1]-i,self.size[0]-i,(i-1))
Und so sieht das ganze dann aus:

Bild

Es ist das "extreme sunken" Textfeld, ich habe einfach ein wx.StaticText mit wx.NO_BORDER und dann den Border selbst gezeichnet.

Das ganze brauch ich um einem Labview Freak der Stunden braucht um die simpelsten Funktionen zusammenzuklicken mal zu zeigen wo der Hammer hängt :D
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hand hat geschrieben:mittlerweile habe ich mein erstes Widget gemacht.
Hi Hand!

Du hast es verstanden :mrgreen:

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Hand hat geschrieben:

Code: Alles auswählen

            if(i == 0): dc.SetPen(wx.Pen(wx.Colour(164,164,164)))
            if(i == 1): dc.SetPen(wx.Pen(wx.Colour(147,147,147)))
            if(i == 2): dc.SetPen(wx.Pen(wx.Colour(136,136,136)))
            if(i == 3): dc.SetPen(wx.Pen(wx.Colour(130,130,130)))
            dc.DrawLine(i,i,self.size[0]-i,i)
            dc.DrawLine(i,i,i,self.size[1]-(i+1))
            if(i == 0): dc.SetPen(wx.Pen(wx.Colour(191,191,191)))
            if(i == 1): dc.SetPen(wx.Pen(wx.Colour(195,195,195)))
            if(i == 2): dc.SetPen(wx.Pen(wx.Colour(190,190,190)))
            if(i == 3): dc.SetPen(wx.Pen(wx.Colour(187,187,187)))
            dc.DrawLine(self.size[0]-i,self.size[1]-i,i,self.size[1]-i)
            dc.DrawLine(self.size[0]-i,self.size[1]-i,self.size[0]-i,(i-1))
Das schreit ja nach einer Liste oder einem Dictionary.
MfG
HWK
Hand
User
Beiträge: 65
Registriert: Sonntag 28. Januar 2007, 14:28

So?

Code: Alles auswählen

class myControl(wx.Panel):
    def __init__(self, parent, pos, size):
        self.size = size
        self.pen_topleft = [wx.Pen((164,164,164)),
                            wx.Pen((147,147,147)),
                            wx.Pen((136,136,136)),
                            wx.Pen((130,130,130))]
        self.pen_bottomright = [wx.Pen((191,191,191)),
                                wx.Pen((195,195,195)),
                                wx.Pen((190,190,190)),
                                wx.Pen((187,187,187))]
        wx.Panel.__init__(self, parent, -1, pos,size)
        self.SetBackgroundColour((179,179,179))
        text = wx.TextCtrl(self, -1, '', (4,4), (self.size[0]-8,self.size[1]-8),
                           style=wx.NO_BORDER)
        text.SetBackgroundColour((210,210,210))
        self.Bind(wx.EVT_PAINT, self._on_paint)

    def _on_paint(self, evt):
        dc = wx.PaintDC(self)
        for i in range(4):
            dc.SetPen(self.pen_topleft[i])
            dc.DrawLine(i,i,self.size[0]-i,i)
            dc.DrawLine(i,i,i,self.size[1]-(i+1))
            dc.SetPen(self.pen_bottomright[i])
            dc.DrawLine(self.size[0]-i,self.size[1]-i,i,self.size[1]-i)
            dc.DrawLine(self.size[0]-i,self.size[1]-i,self.size[0]-i,(i-1))
ohne das wx.Colour gehts komischerweise auch :wink:
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Für Graustufen geht es noch kürzer:

Code: Alles auswählen

class myControl(wx.Panel):
    def __init__(self, parent, pos, size):
        self.size = size
        self.pen_topleft = (164, 147, 136, 130)
        self.pen_bottomright = (191, 195, 190, 187)
        wx.Panel.__init__(self, parent, -1, pos,size)
        self.SetBackgroundColour((179,179,179))
        text = wx.TextCtrl(self, -1, '', (4,4), (self.size[0]-8,self.size[1]-8),
                           style=wx.NO_BORDER)
        text.SetBackgroundColour((210,210,210))
        self.Bind(wx.EVT_PAINT, self._on_paint)

    def _on_paint(self, evt):
        dc = wx.PaintDC(self)
        for i in range(4):
            dc.SetPen(wx.Pen(3 * (self.pen_topleft[i],)))
            dc.DrawLine(i,i,self.size[0]-i,i)
            dc.DrawLine(i,i,i,self.size[1]-(i+1))
            dc.SetPen(wx.Pen(3 * (self.pen_bottomright[i],)))
            dc.DrawLine(self.size[0]-i,self.size[1]-i,i,self.size[1]-i)
            dc.DrawLine(self.size[0]-i,self.size[1]-i,self.size[0]-i,(i-1))
MfG
HWK
Antworten