【问题标题】:wxPython Solitaire GUIwxPython纸牌GUI
【发布时间】:2013-11-15 21:57:43
【问题描述】:

我正在使用 wxPython 编写 Solitaire GUI,并且我在 Windows 7 上。我之前只写过一个 GUI(在 Java Swing 中),所以我对所有不同的东西都不太熟悉小部件和控件的类型。我面临着在 Solitaire 板的 Tableaux 中拥有可调整大小、层叠的卡片堆的挑战。对我来说,为每张卡片使用 BitmapButtons(或至少用于正面卡片)并让面板包含一堆卡片似乎很自然,因为在纸牌中将 Tableau 中的子卡片堆从一堆移动到另一堆是合法的.我确信有更好的方法来做到这一点,但现在我一直在摆弄一个较小的 GUI(不是我的主 GUI)来尝试实现这一点。我在下面附上了测试 GUI 的代码。

注意:我的主 GUI 使用 GridBagSizer 与 14 个单元格。我没有尝试在 GridBagSizer 中使用以下面板/按钮,甚至不知道 GridBagSizer 是否是解决此问题的最佳方式。

import wx

class MyFrame(wx.Frame): 
    def __init__(self, parent, id_, title): 
        wx.Frame.__init__(self, parent, id_, title, size=(810, 580))
        self.panel = wx.Panel(self, size=(72, 320), pos=(20,155))
        self.buttons = []
        self.init_buttons()

    def init_buttons(self):
        for i in range(6):
            face_down = wx.Image('img/cardback.png', wx.BITMAP_TYPE_PNG).ConvertToBitmap()
            wid = face_down.GetWidth()
            hgt = face_down.GetHeight()
            bmpbtn = wx.BitmapButton(self.panel, -1, bitmap=face_down, pos=(20,155+7*i), size=(wid, hgt))
            bmpbtn.Bind(wx.EVT_ENTER_WINDOW, self.onMouseOver)
            self.buttons.append(bmpbtn)
        for i in range(1,14):
            rank = 14 - i
            if i % 2 == 0:
                filename = 'img/%sC.png' % rank
            else:
                filename = 'img/%sH.png' % rank
            img = wx.Image(filename, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
            wid = img.GetWidth()
            hgt = img.GetHeight()
            bmpbtn = wx.BitmapButton(self.panel, -1, bitmap=img, pos=(20, 177+20*i), size=(wid, hgt))
            bmpbtn.Bind(wx.EVT_ENTER_WINDOW, self.onMouseOver)
            self.buttons.append(bmpbtn)

    def onMouseOver(self, event):
        #event.Skip()
        pass

class MyApp(wx.App): 
    def OnInit(self): 
        wx.InitAllImageHandlers() 
        self.frame = MyFrame(None, -1, "Solitaire")         
        self.frame.Show(True) 
        self.SetTopWindow(self.frame) 
        return True 

app = MyApp(0) 
app.MainLoop()

这是运行的结果:

http://oi44.tinypic.com/1zv4swj.jpg

我很满意,直到我将鼠标移到一些按钮上:

http://oi44.tinypic.com/2rdupmq.jpg

这一定与 EVT_ENTER_WINDOW 事件有关。我试图编写一个事件处理程序,但意识到我并不真正知道如何实现我所需要的。根据文档,BitmapButton 的每个状态都有不同的位图 - 悬停、焦点、选定、非活动等。但是,我不想在鼠标悬停事件上更改位图。我只是想让按钮保持原样,而不是显示在其他按钮之上。

任何帮助将不胜感激。顺便说一句,如果有人对实现此 GUI 的更好方法(比 GridBagSizer 和这些按钮面板)提出建议,我会很高兴的!

【问题讨论】:

    标签: button user-interface wxpython


    【解决方案1】:

    我建议不要对每张卡片使用实际的窗口控件。相反,我将有一个单独的画布,您可以在其上将卡片位图呈现在适当的位置。您必须做一些额外的数学运算才能确定点击了哪些卡片,但这绝对是要走的路。

    使用 wx.Panel 和 EVT_PAINT 处理程序来绘制。

    这是一个使用双缓冲来避免闪烁的起点。

    附:您可以使用bitmap = wx.Bitmap(path) 来加载图像,而不是使用wx.Image 并将其转换为位图对象。

    import wx
    
    class Panel(wx.Panel):
        def __init__(self, parent):
            super(Panel, self).__init__(parent)
            self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
            self.Bind(wx.EVT_PAINT, self.on_paint)
            self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down)
            self.Bind(wx.EVT_LEFT_UP, self.on_left_up)
        def on_left_down(self, event):
            print 'on_left_down', event.GetPosition()
        def on_left_up(self, event):
            print 'on_left_up', event.GetPosition()
        def on_paint(self, event):
            dc = wx.AutoBufferedPaintDC(self)
            # Use dc.DrawBitmap(bitmap, x, y) to draw the cards here
    
    class Frame(wx.Frame):
        def __init__(self):
            super(Frame, self).__init__(None)
            self.SetTitle('My Title')
            Panel(self)
    
    def main():
        app = wx.App()
        frame = Frame()
        frame.Center()
        frame.Show()
        app.MainLoop()
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 感谢您的起点代码和快速响应。我希望不必做额外的数学运算,因为面朝下的卡片会比正面的卡片更紧密地间隔在一起。还有一个问题是当用户调整窗口大小时,我的鼠标位置会发生什么?为什么你不建议使用按钮,我如何从使用单个画布中受益?谢谢!
    • 只要你想做任何不是简单位图按钮的图形,你就会被卡住。这就是为什么。而且按照我建议的方式去做并不难。您可以绑定到EVT_SIZE 并重新绘制 (self.Refresh())。您可以在绘制过程中考虑窗口大小以正确绘制它
    • 我一直在摆弄你的代码并想出了一个非常好的 GUI。我没有使用一个面板,而是为所有 13 堆面板制作了面板,这样我就可以使用面板的位置作为偏移量轻松找出点击了哪张卡片。 :) oi42.tinypic.com/348povc.jpg 我不确定为什么有些图片没有正确显示(即垃圾(第二个顶部)堆中的正面朝下图像),但它一定是一个不同的错误。非常感谢您的帮助:)
    • 由于这是我在 stackoverflow 上的第一篇文章,因此我没有足够的声誉来支持您的答案,但这是我的支持 >
    • 您应该能够将其标记为“正确”。如果有人提出更好的答案,您可以随时更改它。
    猜你喜欢
    • 2012-02-29
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    相关资源
    最近更新 更多