Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Button wxPython纸牌GUI_Button_User Interface_Wxpython - Fatal编程技术网

Button wxPython纸牌GUI

Button wxPython纸牌GUI,button,user-interface,wxpython,Button,User Interface,Wxpython,我正在用wxPython编写一个纸牌图形用户界面,我在Windows7上。我以前只写过一个GUI(在JavaSwing中),所以我对所有不同类型的小部件和控件都不太熟悉。我面临着一个挑战,那就是在纸牌板的桌面上有可调整大小、层叠成堆的纸牌。对我来说,对每张牌使用位图按钮(或者至少对正面牌)并让一个面板包含一堆牌似乎很自然,因为在纸牌游戏中从一堆牌移动到另一堆牌是合法的。我相信有更好的方法可以做到这一点,但现在我一直在摆弄一个较小的GUI(不是我的主GUI)来尝试实现这一点。我在下面附上了测试GU

我正在用wxPython编写一个纸牌图形用户界面,我在Windows7上。我以前只写过一个GUI(在JavaSwing中),所以我对所有不同类型的小部件和控件都不太熟悉。我面临着一个挑战,那就是在纸牌板的桌面上有可调整大小、层叠成堆的纸牌。对我来说,对每张牌使用位图按钮(或者至少对正面牌)并让一个面板包含一堆牌似乎很自然,因为在纸牌游戏中从一堆牌移动到另一堆牌是合法的。我相信有更好的方法可以做到这一点,但现在我一直在摆弄一个较小的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()
这就是运行的结果:

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

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


任何帮助都将不胜感激。顺便说一句,如果有人有更好的方法(比GridBagSizer和这些按钮面板)来实现这个GUI的建议,我会喜欢的

我建议不要为每张卡使用实际的窗口控件。相反,我将使用一个画布,在其上渲染适当位置的卡位图。你必须做一点额外的数学来确定哪些卡被点击,但这绝对是一条路要走

使用
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\u SIZE
并重新绘制(self.Refresh())。你可以在画图的时候把窗口的大小考虑进去,以便正确地画出来。我一直在修改你的代码,并想出了一个非常好的GUI。我没有使用一个面板,而是为所有十三个桩制作了面板,这样我就可以很容易地利用面板的位置作为偏移量来确定单击了哪张卡。:)我不确定为什么有些图片出现不正确(例如,垃圾堆(第二顶)中的正面朝下图像),但这一定是另一个错误。非常感谢您的帮助:)由于这是我第一次发表stackoverflow,我没有足够的声誉来支持您的答案,但这是我的支持,您应该能够将其标记为“正确”。如果有人提出更好的答案,你可以随时更改它。