简体   繁体   English

如何在 wxpython GUI 中开发类似组件的图块?

[英]How to develop tiles like components in wxpython GUI?

I have been building a scanner which have multiple scans.我一直在构建具有多次扫描的扫描仪。 I wanted to list them in grid or tiles similar to attached image.我想将它们列在类似于附加图像的网格或图块中。 One approach I am trying is to make Panel class of each tile.我正在尝试的一种方法是制作每个瓷砖的面板 class。 But as there are thousands of scan(tiles) I m concerned about speed and efficiency of program.但是由于有成千上万的扫描(图块),我担心程序的速度和效率。 Design is motivated by this.设计就是以此为动力的。

在此处输入图像描述

First, I've created a class inherited from wx.Panel which will contain a centered image, text and button.首先,我创建了一个继承自 wx.Panel 的 class,其中包含居中的图像、文本和按钮。 In this class, I've created the necessary methods to initialize the panel each time: SetImage, SetText and SetButton.在这个 class 中,我创建了每次初始化面板的必要方法:SetImage、SetText 和 SetButton。 Then, from the main frame class, I initialize several TilePanels to display them.然后,从主框架 class 开始,我初始化了几个 TilePanel 来显示它们。

Finally, I set the same event handler for the button in the main class.最后,我为主 class 中的按钮设置了相同的事件处理程序。

In the case you propose, the trick is in these 2 sizers: wx.BoxSizer and wx.WrapSizer在您提出的情况下,诀窍在于这两个尺寸器: wx.BoxSizerwx.WrapSizer

Take a look at this code (In this case I use a wxWrapSizer because I want the panels to show below each other if they don't fit horizontally):看看这段代码(在这种情况下,我使用 wxWrapSizer,因为如果面板不水平放置,我希望面板显示在彼此下方):

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import wx
from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED


class MainFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MainFrame.__init__
        kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.SetSize((690, 340))
        
        
        
        # Create 3 new panels:
        newPanel = TilePanel(self, wx.ID_ANY)
        newPanel.SetImage(wx.ArtProvider.GetBitmap(wx.ART_INFORMATION, wx.ART_MESSAGE_BOX, size=wx.Size(80,80)))
        newPanel.SetText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum fringilla justo ut ante laoreet consectetur. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.")            
        newPanel.SetButton("View More...", callback=self.OnMyCustomHandler)

        newPanel2 = TilePanel(self, wx.ID_ANY)
        newPanel2.SetImage(wx.ArtProvider.GetBitmap(wx.ART_WARNING, wx.ART_MESSAGE_BOX, size=wx.Size(80,80)))
        newPanel2.SetText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum fringilla justo ut ante laoreet consectetur. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.")            
        newPanel2.SetButton("View More...", callback=self.OnMyCustomHandler)

        newPanel3 = TilePanel(self, wx.ID_ANY)
        newPanel3.SetImage(wx.ArtProvider.GetBitmap(wx.ART_ERROR, wx.ART_MESSAGE_BOX, size=wx.Size(80,80)))
        newPanel3.SetText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum fringilla justo ut ante laoreet consectetur. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.")            
        newPanel3.SetButton("View More...", callback=self.OnMyCustomHandler)
        
        self._panels = []                         
        self._panels.append(newPanel)
        self._panels.append(newPanel2)
        self._panels.append(newPanel3)

        self.__set_properties()
        self.__do_layout()

    def __set_properties(self):
        self.SetTitle("frame")               
        self.SetBackgroundColour(wx.Colour(220, 220, 220))        

    def __do_layout(self):        
        # Create a wrap sizer:
        sizer_1 = wx.WrapSizer(wx.HORIZONTAL)

        # Add panels to the sizer:
        for panel in self._panels:
            sizer_1.Add(panel, 0, wx.ALL, 2)        

        self.SetSizer(sizer_1)
        self.Layout()
        
    def OnMyCustomHandler(self, event):
        print('{} has clicked'.format(event.GetEventObject().GetId()))        


# TilePanel Class
class TilePanel(wx.Panel):
    def __init__(self, *args, **kwds):        
        kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL
        wx.Panel.__init__(self, *args, **kwds)
        self.text_ctrl_1 = ExpandoTextCtrl(self, wx.ID_ANY, "No text set", style=wx.BORDER_NONE | wx.TE_CENTRE | wx.TE_MULTILINE | wx.TE_NO_VSCROLL)
        self.button_1 = wx.Button(self, wx.ID_ANY, "No button text")
        self.stBmp = wx.StaticBitmap(self, wx.ID_ANY)
        self.sizer_flexi = wx.FlexGridSizer(3, 1, 0, 0)
        self.__set_properties()
        self.__do_layout()        

    def __set_properties(self):        
        self.SetBackgroundColour(wx.Colour(255, 255, 255))
        self.text_ctrl_1.SetBackgroundColour(wx.Colour(255, 255, 255))
        self.text_ctrl_1.SetMinSize((200, -1))
        self.button_1.SetMinSize((100, 40))
        self.button_1.SetBackgroundColour(wx.Colour(255, 255, 255))        

    def __do_layout(self):        
        self.SetSizer(self.sizer_flexi)
        self.sizer_flexi.Fit(self)
        self.sizer_flexi.AddGrowableRow(1)
        self.sizer_flexi.AddGrowableCol(0)
        self.Layout()
    
    def SetImage(self, bmp):
        self.stBmp.SetBitmap(bmp)
        self.sizer_flexi.Add(self.stBmp, 0, wx.ALIGN_CENTER | wx.ALL, 10)
        self.Layout()        
        
    def SetText(self, text):
        self.text_ctrl_1.SetValue(text)
        self.sizer_flexi.Add(self.text_ctrl_1, 1, wx.EXPAND | wx.ALL, 10)
        self.Layout()

    def SetButton(self, btnTitle, callback):
        self.button_1.SetLabel(btnTitle)
        self.button_1.Bind(wx.EVT_BUTTON, callback)
        self.sizer_flexi.Add(self.button_1, 0, wx.ALIGN_CENTER | wx.BOTTOM, 10)
        self.Layout()

# end of class TilePanel


# Main App:
class MyApp(wx.App):
    def OnInit(self):
        self.frame = MainFrame(None, wx.ID_ANY, "")
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

# end of class MyApp

if __name__ == "__main__":
    app = MyApp(0)
    app.MainLoop()

And this is the result:这是结果: 在此处输入图像描述

If I had used a wx.BoxSizer instead, the panels would narrow when they don't fit.如果我改用 wx.BoxSizer,面板在不适合时会变窄。 Try it!试试看!

Run, change and test this code until you understand it.运行、更改和测试此代码,直到您理解它为止。

PD: I highly recommend that you use wxGlade to design interfaces in wxPython. PD:我强烈推荐你使用 wxGlade 在 wxPython 中设计界面。 It will help you learn how sizers work much better than any tutorial.它将帮助您了解 sizer 如何比任何教程更好地工作。

http://wxglade.sourceforge.net/ http://wxglade.sourceforge.net/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM