wxPython 简单的 GUI 难以捉摸
wxPython simple GUI proving elusive
我已经在 Python 3.8 和 GNU/Linux 上的 wxPython 4 (Phoenix) 工作了很多天,但进展甚微。我需要一个非常简单的 GUI,滚动 canvas 占据全屏 window 的大部分,滚动面板在其下方包含大约 4 行文本。我想在 canvas 和面板周围留出一些余量。我希望能够自动定位(而不是绝对)。我遇到的问题是 1) 滚动条没有出现,2) 我使用的是绝对定位,我不确定我放置的 sizer 是否正常工作。
我一直在四处寻找,尝试各种变体。我已经阅读了我使用的所有调用的 API 文档。我看过演示和示例。我看过我能在 O'Reilly 上找到的每一本书。我仍然觉得我在理解 wxPython 的架构上有点一头雾水。我在 Python 中用 TkInter 和 Qt 以及其他语言开发了许多其他 GUI 应用程序。所以,我在这里感觉很密集。
这是当前应用的样子:
这是我当前的代码:
#!/usr/bin/env python3.8
import wx
class MainWindow(wx.Frame):
def __init__(self, title):
screen_x = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
screen_y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
size_value = wx.Size(screen_x, screen_y)
wx.Frame.__init__(self, None, title=title, size=size_value)
# why does this not work?
# super(MainWindow, self).__init__(self, None, title=title,
# size=size_value)
canvas1 = wx.ScrolledCanvas(self, size=wx.Size(screen_x-30, 300),
pos=wx.Point(15, 15))
canvas1.SetBackgroundColour('#cc20cc')
canvas1.AlwaysShowScrollbars(True, True)
canvas1.SetAutoLayout(1)
canvas1.SetScrollbar(wx.VERTICAL, 0, 10, 100)
canvas1.SetScrollbar(wx.HORIZONTAL, 0, 10, 100)
canvas1.SetScrollRate(1, 1)
# with open('/home/kbuchs/.emacs') as fp:
# txt_value = fp.read()
# txt = wx.StaticText(canvas1, label=txt_value)
canvas2 = wx.ScrolledCanvas(self, size=wx.Size(screen_x-30, 1000),
pos=wx.Point(15, 315))
canvas2.SetBackgroundColour('#d0d020')
canvas2.AlwaysShowScrollbars(True, True)
canvas2.SetAutoLayout(1)
canvas2.SetScrollRate(1, 1)
with open('/home/kbuchs/.bashrc') as fp:
txt_value2 = fp.read()
txt2 = wx.StaticText(canvas2, label=txt_value2)
sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = sizer
sizer.Add(canvas1, wx.ID_ANY, wx.ALL, 20)
sizer.Add(canvas2, wx.ID_ANY, wx.ALL, 40)
self.Show()
app = wx.App()
MainWindow('Git Branch History')
app.MainLoop()
更新 6/3 10:30 下午 CDT。
这是我在 Rolf of Saxony 的示例之后对代码的最新修订尝试。这两个 txt 部分(如果未注释)似乎没有写入 canvas/panels,但它们在框架的顶部重叠。另外,仍然没有滚动。
#!/usr/bin/env python3.8
import wx
import wx.lib.scrolledpanel as sp
class MainWindow(wx.Frame):
def __init__(self, title):
screen_x = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
screen_y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
size_value = wx.Size(screen_x, screen_y)
super(MainWindow, self).__init__(None, title=title, size=size_value)
# canvas1 = wx.ScrolledCanvas(self, id=-1,
canvas1 = sp.ScrolledPanel(self, id=-1,
size=wx.Size(screen_x, screen_y-200))
# pos=wx.Point(15, 15))
canvas1.SetBackgroundColour('#ccffff')
canvas1.AlwaysShowScrollbars(True, True)
canvas1.SetAutoLayout(1)
canvas1.SetupScrolling()
with open('/home/kbuchs/.emacs') as fp:
txt_value1 = fp.read()
long_line = 900*'-' + '\n'
# txt1 = wx.StaticText(canvas1, label=long_line+txt_value1)
# txt1.SetBackgroundColour('#eeffff')
# txt1Sizer = wx.BoxSizer(wx.VERTICAL)
# txt1Sizer.Add(txt1, proportion=0, border=5)
canvas1Sizer = wx.BoxSizer(wx.VERTICAL)
canvas1Sizer.Add(canvas1, proportion=0, flag=wx.CENTER|wx.ALL|wx.EXPAND, border=5)
# canvas1Sizer.Add(txt1Sizer, proportion=0)
# canvas1Sizer.Add(txt1, proportion=0, flag=wx.ALL, border=5)
# canvas2 = wx.ScrolledCanvas(self, id=-1,
canvas2 = sp.ScrolledPanel(self, id=-1,
size=wx.Size(screen_x, 200))
# pos=wx.Point(15, 315))
canvas2.SetBackgroundColour('#ffffcc')
canvas2.AlwaysShowScrollbars(True, True)
canvas2.SetAutoLayout(1)
canvas2.SetupScrolling()
with open('/home/kbuchs/.bashrc') as fp:
txt_value2 = fp.read()
# txt2 = wx.StaticText(canvas2, label=long_line+txt_value2)
# txt2.SetBackgroundColour('#ffffee')
canvas2Sizer = wx.BoxSizer(wx.VERTICAL)
canvas2Sizer.Add(canvas2, proportion=0, flag=wx.CENTER|wx.ALL|wx.EXPAND, border=5)
# canvas2Sizer.Add(txt2, proportion=0, flag=wx.CENTER|wx.ALL, border=20)
sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = sizer
sizer.Add(canvas1Sizer, proportion=0, flag=wx.CENTER|wx.ALL|wx.EXPAND, border=5)
sizer.Add(canvas2Sizer, proportion=0, flag=wx.CENTER|wx.ALL|wx.EXPAND, border=5)
self.Show()
app = wx.App()
MainWindow('Git Branch History')
app.MainLoop()
我要把你的canvas扔掉,换成TextCtrl,你可以用任何符合你要求的东西。
希望这会为您指明正确的方向,其中有足够的内容可以指明方向。
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, title):
screen_x = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
screen_y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
size_value = wx.Size(screen_x, screen_y)
super(MainWindow, self).__init__(parent, title=title, size=size_value)
#Define widgets
tc1 = wx.TextCtrl(self, size=wx.Size(screen_x-30, 200),
style= wx.TE_MULTILINE|wx.TE_PROCESS_ENTER|wx.TE_DONTWRAP|wx.TE_AUTO_URL)
tc1.SetBackgroundColour('#cc2000')
# Some Control buttons
self.b1 = wx.Button(self, -1, "Button 1")
self.b2 = wx.Button(self, -1, "Button 2")
self.b3 = wx.Button(self, -1, "Quit")
tc2 = wx.TextCtrl(self, size=wx.Size(screen_x-30, 1000),
style= wx.TE_MULTILINE|wx.TE_PROCESS_ENTER|wx.TE_DONTWRAP)
tc2.SetBackgroundColour('#d0d020')
#Bind events to functions
self.b3.Bind(wx.EVT_BUTTON, self.OnQuit)
#Load initial data
try:
with open('tips.txt') as fp:
txt_value2 = fp.read()
except:
txt_value2 = "tips.txt file not found"
txt_value2 = txt_value2 * 20
tc1.AppendText("No data yet\n")
tc1.AppendText("www.nodatayet.com\n")
tc1.AppendText(" "*20)
tc1.AppendText("X\n")
tc2.write(txt_value2)
#Define sizers
sizer = wx.BoxSizer(wx.VERTICAL)
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
#Populate sizers
button_sizer.Add(self.b1)
button_sizer.Add(self.b2)
button_sizer.Add(self.b3)
sizer.Add(tc1, proportion=0, flag=wx.ALL, border=20)
sizer.Add(button_sizer, proportion=0, flag=wx.LEFT, border=40)
sizer.Add(tc2, proportion=1, flag=wx.ALL, border=40)
self.SetSizer(sizer)
self.Show()
def OnQuit(self, event):
self.Destroy()
app = wx.App()
MainWindow(None,'Git Branch History')
app.MainLoop()
我会再试一次,因为你修改了问题但没有发表评论,所以我不知道。
你似乎对 SetSizer
有一个盲点,在评论中提到了两次并在我的第一个答案中使用了。
这就像收拾行李箱,然后背着背包去度假。
这是您的第二个代码示例,已修改。
import wx
import wx.lib.scrolledpanel as sp
class MainWindow(wx.Frame):
def __init__(self, title):
screen_x = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
screen_y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
size_value = wx.Size(screen_x, screen_y)
super(MainWindow, self).__init__(None, title=title, size=size_value)
canvas1 = sp.ScrolledPanel(self, id=-1,)
canvas1.SetBackgroundColour('#ccffff')
canvas1.SetupScrolling(scroll_x=True, scroll_y=True, rate_x=20, rate_y=20, scrollToTop=True, scrollIntoView=True)
canvas1.AlwaysShowScrollbars(True, True)
with open('tips.txt') as fp:
txt_value1 = fp.read()
long_line = 600*'y' + 'X\n'
txt1 = wx.StaticText(canvas1, label=long_line+txt_value1)
txt1.SetBackgroundColour('#eeffff')
canvas1Sizer = wx.BoxSizer(wx.VERTICAL)
canvas1Sizer.Add(txt1, proportion=0, flag=wx.ALL|wx.EXPAND, border=5)
canvas2 = sp.ScrolledPanel(self, id=-1)
canvas2.SetBackgroundColour('#ffffcc')
canvas2.SetupScrolling(scroll_x=True, scroll_y=True, rate_x=20, rate_y=20, scrollToTop=True, scrollIntoView=True)
canvas2.AlwaysShowScrollbars(True, True)
with open('tips.txt') as fp:
txt_value2 = fp.read()
txt2 = wx.StaticText(canvas2, label=long_line+txt_value2)
txt2.SetBackgroundColour('#ffffee')
canvas2Sizer = wx.BoxSizer(wx.VERTICAL)
canvas2Sizer.Add(txt2, proportion=0, flag=wx.ALL|wx.EXPAND, border=20)
canvas1.SetSizer(canvas1Sizer)
canvas2.SetSizer(canvas2Sizer)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(canvas1, proportion=1, flag=wx.ALL|wx.EXPAND, border=5)
sizer.Add(canvas2, proportion=1, flag=wx.ALL|wx.EXPAND, border=5)
self.SetSizer(sizer)
self.Show()
app = wx.App()
MainWindow('Git Branch History')
app.MainLoop()
我已经在 Python 3.8 和 GNU/Linux 上的 wxPython 4 (Phoenix) 工作了很多天,但进展甚微。我需要一个非常简单的 GUI,滚动 canvas 占据全屏 window 的大部分,滚动面板在其下方包含大约 4 行文本。我想在 canvas 和面板周围留出一些余量。我希望能够自动定位(而不是绝对)。我遇到的问题是 1) 滚动条没有出现,2) 我使用的是绝对定位,我不确定我放置的 sizer 是否正常工作。
我一直在四处寻找,尝试各种变体。我已经阅读了我使用的所有调用的 API 文档。我看过演示和示例。我看过我能在 O'Reilly 上找到的每一本书。我仍然觉得我在理解 wxPython 的架构上有点一头雾水。我在 Python 中用 TkInter 和 Qt 以及其他语言开发了许多其他 GUI 应用程序。所以,我在这里感觉很密集。
这是当前应用的样子:
这是我当前的代码:
#!/usr/bin/env python3.8
import wx
class MainWindow(wx.Frame):
def __init__(self, title):
screen_x = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
screen_y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
size_value = wx.Size(screen_x, screen_y)
wx.Frame.__init__(self, None, title=title, size=size_value)
# why does this not work?
# super(MainWindow, self).__init__(self, None, title=title,
# size=size_value)
canvas1 = wx.ScrolledCanvas(self, size=wx.Size(screen_x-30, 300),
pos=wx.Point(15, 15))
canvas1.SetBackgroundColour('#cc20cc')
canvas1.AlwaysShowScrollbars(True, True)
canvas1.SetAutoLayout(1)
canvas1.SetScrollbar(wx.VERTICAL, 0, 10, 100)
canvas1.SetScrollbar(wx.HORIZONTAL, 0, 10, 100)
canvas1.SetScrollRate(1, 1)
# with open('/home/kbuchs/.emacs') as fp:
# txt_value = fp.read()
# txt = wx.StaticText(canvas1, label=txt_value)
canvas2 = wx.ScrolledCanvas(self, size=wx.Size(screen_x-30, 1000),
pos=wx.Point(15, 315))
canvas2.SetBackgroundColour('#d0d020')
canvas2.AlwaysShowScrollbars(True, True)
canvas2.SetAutoLayout(1)
canvas2.SetScrollRate(1, 1)
with open('/home/kbuchs/.bashrc') as fp:
txt_value2 = fp.read()
txt2 = wx.StaticText(canvas2, label=txt_value2)
sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = sizer
sizer.Add(canvas1, wx.ID_ANY, wx.ALL, 20)
sizer.Add(canvas2, wx.ID_ANY, wx.ALL, 40)
self.Show()
app = wx.App()
MainWindow('Git Branch History')
app.MainLoop()
更新 6/3 10:30 下午 CDT。 这是我在 Rolf of Saxony 的示例之后对代码的最新修订尝试。这两个 txt 部分(如果未注释)似乎没有写入 canvas/panels,但它们在框架的顶部重叠。另外,仍然没有滚动。
#!/usr/bin/env python3.8
import wx
import wx.lib.scrolledpanel as sp
class MainWindow(wx.Frame):
def __init__(self, title):
screen_x = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
screen_y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
size_value = wx.Size(screen_x, screen_y)
super(MainWindow, self).__init__(None, title=title, size=size_value)
# canvas1 = wx.ScrolledCanvas(self, id=-1,
canvas1 = sp.ScrolledPanel(self, id=-1,
size=wx.Size(screen_x, screen_y-200))
# pos=wx.Point(15, 15))
canvas1.SetBackgroundColour('#ccffff')
canvas1.AlwaysShowScrollbars(True, True)
canvas1.SetAutoLayout(1)
canvas1.SetupScrolling()
with open('/home/kbuchs/.emacs') as fp:
txt_value1 = fp.read()
long_line = 900*'-' + '\n'
# txt1 = wx.StaticText(canvas1, label=long_line+txt_value1)
# txt1.SetBackgroundColour('#eeffff')
# txt1Sizer = wx.BoxSizer(wx.VERTICAL)
# txt1Sizer.Add(txt1, proportion=0, border=5)
canvas1Sizer = wx.BoxSizer(wx.VERTICAL)
canvas1Sizer.Add(canvas1, proportion=0, flag=wx.CENTER|wx.ALL|wx.EXPAND, border=5)
# canvas1Sizer.Add(txt1Sizer, proportion=0)
# canvas1Sizer.Add(txt1, proportion=0, flag=wx.ALL, border=5)
# canvas2 = wx.ScrolledCanvas(self, id=-1,
canvas2 = sp.ScrolledPanel(self, id=-1,
size=wx.Size(screen_x, 200))
# pos=wx.Point(15, 315))
canvas2.SetBackgroundColour('#ffffcc')
canvas2.AlwaysShowScrollbars(True, True)
canvas2.SetAutoLayout(1)
canvas2.SetupScrolling()
with open('/home/kbuchs/.bashrc') as fp:
txt_value2 = fp.read()
# txt2 = wx.StaticText(canvas2, label=long_line+txt_value2)
# txt2.SetBackgroundColour('#ffffee')
canvas2Sizer = wx.BoxSizer(wx.VERTICAL)
canvas2Sizer.Add(canvas2, proportion=0, flag=wx.CENTER|wx.ALL|wx.EXPAND, border=5)
# canvas2Sizer.Add(txt2, proportion=0, flag=wx.CENTER|wx.ALL, border=20)
sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer = sizer
sizer.Add(canvas1Sizer, proportion=0, flag=wx.CENTER|wx.ALL|wx.EXPAND, border=5)
sizer.Add(canvas2Sizer, proportion=0, flag=wx.CENTER|wx.ALL|wx.EXPAND, border=5)
self.Show()
app = wx.App()
MainWindow('Git Branch History')
app.MainLoop()
我要把你的canvas扔掉,换成TextCtrl,你可以用任何符合你要求的东西。
希望这会为您指明正确的方向,其中有足够的内容可以指明方向。
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, title):
screen_x = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
screen_y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
size_value = wx.Size(screen_x, screen_y)
super(MainWindow, self).__init__(parent, title=title, size=size_value)
#Define widgets
tc1 = wx.TextCtrl(self, size=wx.Size(screen_x-30, 200),
style= wx.TE_MULTILINE|wx.TE_PROCESS_ENTER|wx.TE_DONTWRAP|wx.TE_AUTO_URL)
tc1.SetBackgroundColour('#cc2000')
# Some Control buttons
self.b1 = wx.Button(self, -1, "Button 1")
self.b2 = wx.Button(self, -1, "Button 2")
self.b3 = wx.Button(self, -1, "Quit")
tc2 = wx.TextCtrl(self, size=wx.Size(screen_x-30, 1000),
style= wx.TE_MULTILINE|wx.TE_PROCESS_ENTER|wx.TE_DONTWRAP)
tc2.SetBackgroundColour('#d0d020')
#Bind events to functions
self.b3.Bind(wx.EVT_BUTTON, self.OnQuit)
#Load initial data
try:
with open('tips.txt') as fp:
txt_value2 = fp.read()
except:
txt_value2 = "tips.txt file not found"
txt_value2 = txt_value2 * 20
tc1.AppendText("No data yet\n")
tc1.AppendText("www.nodatayet.com\n")
tc1.AppendText(" "*20)
tc1.AppendText("X\n")
tc2.write(txt_value2)
#Define sizers
sizer = wx.BoxSizer(wx.VERTICAL)
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
#Populate sizers
button_sizer.Add(self.b1)
button_sizer.Add(self.b2)
button_sizer.Add(self.b3)
sizer.Add(tc1, proportion=0, flag=wx.ALL, border=20)
sizer.Add(button_sizer, proportion=0, flag=wx.LEFT, border=40)
sizer.Add(tc2, proportion=1, flag=wx.ALL, border=40)
self.SetSizer(sizer)
self.Show()
def OnQuit(self, event):
self.Destroy()
app = wx.App()
MainWindow(None,'Git Branch History')
app.MainLoop()
我会再试一次,因为你修改了问题但没有发表评论,所以我不知道。
你似乎对 SetSizer
有一个盲点,在评论中提到了两次并在我的第一个答案中使用了。
这就像收拾行李箱,然后背着背包去度假。
这是您的第二个代码示例,已修改。
import wx
import wx.lib.scrolledpanel as sp
class MainWindow(wx.Frame):
def __init__(self, title):
screen_x = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
screen_y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
size_value = wx.Size(screen_x, screen_y)
super(MainWindow, self).__init__(None, title=title, size=size_value)
canvas1 = sp.ScrolledPanel(self, id=-1,)
canvas1.SetBackgroundColour('#ccffff')
canvas1.SetupScrolling(scroll_x=True, scroll_y=True, rate_x=20, rate_y=20, scrollToTop=True, scrollIntoView=True)
canvas1.AlwaysShowScrollbars(True, True)
with open('tips.txt') as fp:
txt_value1 = fp.read()
long_line = 600*'y' + 'X\n'
txt1 = wx.StaticText(canvas1, label=long_line+txt_value1)
txt1.SetBackgroundColour('#eeffff')
canvas1Sizer = wx.BoxSizer(wx.VERTICAL)
canvas1Sizer.Add(txt1, proportion=0, flag=wx.ALL|wx.EXPAND, border=5)
canvas2 = sp.ScrolledPanel(self, id=-1)
canvas2.SetBackgroundColour('#ffffcc')
canvas2.SetupScrolling(scroll_x=True, scroll_y=True, rate_x=20, rate_y=20, scrollToTop=True, scrollIntoView=True)
canvas2.AlwaysShowScrollbars(True, True)
with open('tips.txt') as fp:
txt_value2 = fp.read()
txt2 = wx.StaticText(canvas2, label=long_line+txt_value2)
txt2.SetBackgroundColour('#ffffee')
canvas2Sizer = wx.BoxSizer(wx.VERTICAL)
canvas2Sizer.Add(txt2, proportion=0, flag=wx.ALL|wx.EXPAND, border=20)
canvas1.SetSizer(canvas1Sizer)
canvas2.SetSizer(canvas2Sizer)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(canvas1, proportion=1, flag=wx.ALL|wx.EXPAND, border=5)
sizer.Add(canvas2, proportion=1, flag=wx.ALL|wx.EXPAND, border=5)
self.SetSizer(sizer)
self.Show()
app = wx.App()
MainWindow('Git Branch History')
app.MainLoop()