简体   繁体   English

WxPython的ScrolledWindow元素折叠到最小尺寸

[英]WxPython's ScrolledWindow element collapses to minimum size

I am using a Panel within a Frame to display images (the GUI need to switch between multiple panels and hence the hierarchy). 我正在框架中使用面板来显示图像(GUI需要在多个面板之间切换,因此需要在层次结构之间进行切换)。 As images should be displayed in native size I used ScrolledWindow as the panel parent. 由于图像应以原始大小显示,因此我使用ScrolledWindow作为面板父级。 The scrolls do appear and work, but it causes the Panel to collapse to minimum size and it needs to be resized using drag&drop every time. 滚动确实可以正常工作,但是会导致面板折叠到最小尺寸,并且每次都需要使用拖放来调整其大小。 Is there a way around this? 有没有解决的办法?

Below is a reduced version of the code, which shows the problem: 下面是该代码的简化版本,它显示了该问题:

import os
import wx
from wx.lib.pubsub import pub


class Edit_Panel(wx.PyScrolledWindow):
    def __init__(self, parent):
        super(Edit_Panel, self).__init__(parent)

        # Display size
        width, height = wx.DisplaySize()
        self.photoMaxSize = height - 500

        # Loaded image
        self.loaded_image = None

        # Icons
        self.open_icon_id = 500

        # Generate panel
        self.layout()

    def layout(self):
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)

        divider = wx.StaticLine(self, -1, style = wx.LI_HORIZONTAL)
        self.main_sizer.Add(divider, 0, wx.ALL | wx.EXPAND)

        self.toolbar = self.init_toolbar()
        self.main_sizer.Add(self.toolbar, 0, wx.ALL)

        img = wx.EmptyImage(self.photoMaxSize, self.photoMaxSize)
        self.image_control = wx.StaticBitmap(self, wx.ID_ANY,
                                             wx.BitmapFromImage(img))
        self.main_sizer.Add(self.image_control, 0, wx.ALL | wx.CENTER, 5)

        self.image_label = wx.StaticText(self, -1, style = wx.ALIGN_CENTRE)
        self.main_sizer.Add(self.image_label, 0, wx.ALL | wx.ALIGN_CENTRE, 5)

        self.SetSizer(self.main_sizer)

        fontsz = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT).GetPixelSize()
        self.SetScrollRate(fontsz.x, fontsz.y)
        self.EnableScrolling(True, True)

    def init_toolbar(self):
        toolbar = wx.ToolBar(self)
        toolbar.SetToolBitmapSize((16, 16))

        open_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (16, 16))
        open_tool = toolbar.AddSimpleTool(self.open_icon_id, open_ico, "Open", "Open an Image Directory")
        handler = self.on_open_reference
        self.Bind(event = wx.EVT_MENU, handler = handler, source = open_tool)

        toolbar.Realize()

        return toolbar

    def on_open_reference(self, event, wildcard = None):
        if wildcard is None:
            wildcard = self.get_wildcard()

        defaultDir = '~/'
        dbox = wx.FileDialog(self, "Choose an image to display", defaultDir = defaultDir, wildcard = wildcard, style = wx.OPEN)

        if dbox.ShowModal() == wx.ID_OK:
            file_name = dbox.GetPath()

            # load image
            self.load_image(image = file_name)

        dbox.Destroy()

    def get_wildcard(self):
        wildcard = 'Image files (*.jpg;*.png;*.bmp)|*.png;*.bmp;*.jpg;*.jpeg'
        return wildcard

    def load_image(self, image):
        self.loaded_image = image

        # Load image
        img = wx.Image(image, wx.BITMAP_TYPE_ANY)

        # Label image name
        image_name = os.path.basename(image)
        self.image_label.SetLabel(image_name)

        # scale the image, preserving the aspect ratio
        scale_image = True
        if scale_image:
            W = img.GetWidth()
            H = img.GetHeight()
            if W > H:
                NewW = self.photoMaxSize
                NewH = self.photoMaxSize * H / W
            else:
                NewH = self.photoMaxSize
                NewW = self.photoMaxSize * W / H
            img = img.Scale(NewW, NewH)

        self.image_control.SetBitmap(wx.BitmapFromImage(img))

        # Render
        self.main_sizer.Layout()

        self.main_sizer.Fit(self)
        self.Refresh()

        pub.sendMessage("resize", msg = "")


class Viewer_Frame(wx.Frame):
    def __init__(self, parent, id, title):
        super(Viewer_Frame, self).__init__(parent = parent, id = id, title = title)

        # Edit panel
        self.edit_panel = Edit_Panel(self)

        # Default panel
        self.main_panel = self.edit_panel

        # Render frame
        self.render_frame()

        # Subscription to re-render
        pub.subscribe(self.resize_frame, ("resize"))

    def render_frame(self):
        # Main Sizer
        self.main_sizer = wx.BoxSizer(wx.VERTICAL)

        # Add default sizer
        self.main_sizer.Add(self.main_panel, 1, wx.EXPAND)

        # Render
        self.SetSizer(self.main_sizer)
        self.Show()
        self.main_sizer.Fit(self)
        self.Center()


    def resize_frame(self, msg):
        self.main_sizer.Fit(self)


if __name__ == "__main__":
    app = wx.App(False)
    frame = Viewer_Frame(parent = None, id = -1, title = 'Toolkit')
    app.MainLoop()

You're calling Fit() , so you're explicitly asking the panel to fit its contents, but you don't specify the min/best size of this contents anywhere (AFAICS, there is a lot of code here, so I could be missing something). 您正在调用Fit() ,因此您明确要求面板使其内容合适,但是您没有在任何地方指定此内容的最小/最佳大小(AFAICS,这里有很多代码,因此我可以缺少一些东西)。

If you want to use some minimal size for the panel, just set it using SetMinSize() . 如果要为面板使用一些最小尺寸,只需使用SetMinSize()

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

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