Python 3.x wxPython应用程序在库更新后完全中断:wxTextCtrl不工作,对话框按钮崩溃
我已经在Ubuntu18.04上使用wxPython制作了一个应用程序,使用的版本是Python 3.x wxPython应用程序在库更新后完全中断:wxTextCtrl不工作,对话框按钮崩溃,python-3.x,wxpython,wxwidgets,Python 3.x,Wxpython,Wxwidgets,我已经在Ubuntu18.04上使用wxPython制作了一个应用程序,使用的版本是python-wxgtk2.8。这个软件包在我从Scarch安装系统后不再可用,但这并不重要。我现在尝试了python-wxgtk3.0和python3-wxgtk4.0(仅更改代码以支持python3)。突然,出现了问题 首先,在WXTEXTCRL中,插入符号不可见,即使我可以键入。调用SetValue()(我用它来实现语法高亮显示)时,EVT_TEXT事件也没有传递。其次,当允许使用Fit()调整大小时,使用
python-wxgtk2.8
。这个软件包在我从Scarch安装系统后不再可用,但这并不重要。我现在尝试了python-wxgtk3.0
和python3-wxgtk4.0
(仅更改代码以支持python3)。突然,出现了问题
首先,在WXTEXTCRL中,插入符号不可见,即使我可以键入。调用SetValue()
(我用它来实现语法高亮显示)时,EVT_TEXT事件也没有传递。其次,当允许使用Fit()
调整大小时,使用CreateSeparatedButtonSizer()
添加到自定义对话框的按钮的高度正好为1像素
对话框代码如下所示:
class NewProjectDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, title="New project...")
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
label = wx.StaticText(self, -1, "Name of the project (as shown in the editor):")
sizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 2)
self.ctrlName = wx.TextCtrl(self)
sizer.Add(self.ctrlName, 0, wx.EXPAND|wx.ALL, 2)
sizer.Add(wx.StaticText(self, -1, "Project directory (containing the 'configure' file and optinally '.git'):"), 0, wx.ALIGN_LEFT|wx.ALL, 2)
self.ctrlDir = wx.DirPickerCtrl(self)
sizer.Add(self.ctrlDir, 0, wx.EXPAND|wx.ALL, 2)
self.cbInit = wx.CheckBox(self, -1, "Initialize this project with an MBS configuration template")
sizer.Add(self.cbInit, 0, wx.ALIGN_LEFT|wx.ALL, 2)
self.chTempl = wx.Choice(self)
self.chTempl.Disable()
for label, callback in MBS_TEMPLATES:
self.chTempl.Append(label, callback)
self.chTempl.SetSelection(0)
sizer.Add(self.chTempl, 0, wx.EXPAND|wx.ALL, 2)
sizer.Add(self.CreateSeparatedButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND|wx.ALL, 2)
self.Fit()
self.Bind(wx.EVT_CHECKBOX, self.onInitChange)
self.Bind(wx.EVT_BUTTON, self.onOK, id = wx.ID_OK)
def onInitChange(self, e):
if self.cbInit.IsChecked():
self.chTempl.Enable()
else:
self.chTempl.Disable()
def onOK(self, e):
if len(self.ctrlName.GetValue()) == 0:
wx.MessageBox("Please specify a project name!", "New project", wx.ICON_ERROR)
return
elif not os.path.isdir(self.ctrlDir.GetPath()):
wx.MessageBox("Please specify a project directory!", "New project", wx.ICON_ERROR)
return
else:
path = self.ctrlDir.GetPath()
if self.cbInit.IsChecked():
members = os.listdir(path)
if ".git" in members:
members.remove(".git")
if len(members) != 0:
wx.MessageBox("In order to initialize a project, you must point me to an EMPTY directory (or one with only a '.git' folder)!",
"New project", wx.ICON_ERROR)
return
e.Skip()
def getProjectName(self):
return self.ctrlName.GetValue()
def getProjectDir(self):
return self.ctrlDir.GetPath()
def getInitCallback(self):
if self.cbInit.IsChecked():
return self.chTempl.GetClientData(self.chTempl.GetSelection())
else:
return None
class CodeEditor(wx.TextCtrl):
def __init__(self, parent):
wx.TextCtrl.__init__(self, parent, style=wx.TE_MULTILINE | wx.TE_RICH2 | wx.TE_PROCESS_TAB | wx.TE_PROCESS_ENTER)
self.SetFont(wx.Font(userConfig["CodeEditor.FontSize"], wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, userConfig["CodeEditor.FontFamily"]))
self.SetBackgroundColour(wx.Colour(*userConfig["CodeEditor.Background"]))
self.SetForegroundColour(wx.Colour(*userConfig["CodeEditor.Foreground"]))
self.attrNull = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Foreground"]))
self.attrKeyword = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.Keyword"]))
self.attrString = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.String"]))
self.attrNumber = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.Number"]))
self.attrUserType = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.UserType"]))
self.attrComment = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.Comment"]))
self.attrPreprocessor = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.Preprocessor"]))
self.Bind(wx.EVT_TEXT, self.onUpdate)
self.Bind(wx.EVT_TEXT_ENTER, self.onEnter)
self.file = None
self.attrs = {
"keyword": self.attrKeyword,
"string": self.attrString,
"number": self.attrNumber,
"userType": self.attrUserType,
"comment": self.attrComment,
"preprocessor": self.attrPreprocessor
}
self.SetValue("No file was selected yet!\nPlease select one from the Navigator.")
self.Disable()
def setFile(self, efile):
content = efile.read()
if content is not None:
self.file = efile
self.Enable()
self.SetValue(content)
def onEnter(self, e):
if self.file is None:
return
pos = self.GetInsertionPoint()
code = self.GetValue()
before = code[:pos]
after = code[pos:]
beforeText, afterText = self.file.getMode().getContextualNewline(before, after)
self.WriteText(beforeText)
pos = self.GetInsertionPoint()
self.WriteText(afterText)
self.SetInsertionPoint(pos)
def onUpdate(self, e):
if self.file is None:
e.Skip()
return
code = self.GetValue()
toker = Tokenizer(code)
self.file.getMode().colorize(toker)
self.file.update(code)
# clear the current styles
self.SetStyle(0, self.GetLastPosition(), self.attrNull)
for startPos, endPos, attr in toker.tokens:
self.SetStyle(startPos, endPos, self.attrs[attr])
e.Skip()
这将产生:
如您所见,OK和Cancel按钮在任何地方都看不到
代码编辑器小部件代码如下所示:
class NewProjectDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent, title="New project...")
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
label = wx.StaticText(self, -1, "Name of the project (as shown in the editor):")
sizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 2)
self.ctrlName = wx.TextCtrl(self)
sizer.Add(self.ctrlName, 0, wx.EXPAND|wx.ALL, 2)
sizer.Add(wx.StaticText(self, -1, "Project directory (containing the 'configure' file and optinally '.git'):"), 0, wx.ALIGN_LEFT|wx.ALL, 2)
self.ctrlDir = wx.DirPickerCtrl(self)
sizer.Add(self.ctrlDir, 0, wx.EXPAND|wx.ALL, 2)
self.cbInit = wx.CheckBox(self, -1, "Initialize this project with an MBS configuration template")
sizer.Add(self.cbInit, 0, wx.ALIGN_LEFT|wx.ALL, 2)
self.chTempl = wx.Choice(self)
self.chTempl.Disable()
for label, callback in MBS_TEMPLATES:
self.chTempl.Append(label, callback)
self.chTempl.SetSelection(0)
sizer.Add(self.chTempl, 0, wx.EXPAND|wx.ALL, 2)
sizer.Add(self.CreateSeparatedButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND|wx.ALL, 2)
self.Fit()
self.Bind(wx.EVT_CHECKBOX, self.onInitChange)
self.Bind(wx.EVT_BUTTON, self.onOK, id = wx.ID_OK)
def onInitChange(self, e):
if self.cbInit.IsChecked():
self.chTempl.Enable()
else:
self.chTempl.Disable()
def onOK(self, e):
if len(self.ctrlName.GetValue()) == 0:
wx.MessageBox("Please specify a project name!", "New project", wx.ICON_ERROR)
return
elif not os.path.isdir(self.ctrlDir.GetPath()):
wx.MessageBox("Please specify a project directory!", "New project", wx.ICON_ERROR)
return
else:
path = self.ctrlDir.GetPath()
if self.cbInit.IsChecked():
members = os.listdir(path)
if ".git" in members:
members.remove(".git")
if len(members) != 0:
wx.MessageBox("In order to initialize a project, you must point me to an EMPTY directory (or one with only a '.git' folder)!",
"New project", wx.ICON_ERROR)
return
e.Skip()
def getProjectName(self):
return self.ctrlName.GetValue()
def getProjectDir(self):
return self.ctrlDir.GetPath()
def getInitCallback(self):
if self.cbInit.IsChecked():
return self.chTempl.GetClientData(self.chTempl.GetSelection())
else:
return None
class CodeEditor(wx.TextCtrl):
def __init__(self, parent):
wx.TextCtrl.__init__(self, parent, style=wx.TE_MULTILINE | wx.TE_RICH2 | wx.TE_PROCESS_TAB | wx.TE_PROCESS_ENTER)
self.SetFont(wx.Font(userConfig["CodeEditor.FontSize"], wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, userConfig["CodeEditor.FontFamily"]))
self.SetBackgroundColour(wx.Colour(*userConfig["CodeEditor.Background"]))
self.SetForegroundColour(wx.Colour(*userConfig["CodeEditor.Foreground"]))
self.attrNull = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Foreground"]))
self.attrKeyword = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.Keyword"]))
self.attrString = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.String"]))
self.attrNumber = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.Number"]))
self.attrUserType = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.UserType"]))
self.attrComment = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.Comment"]))
self.attrPreprocessor = wx.TextAttr(wx.Colour(*userConfig["CodeEditor.Syntax.Preprocessor"]))
self.Bind(wx.EVT_TEXT, self.onUpdate)
self.Bind(wx.EVT_TEXT_ENTER, self.onEnter)
self.file = None
self.attrs = {
"keyword": self.attrKeyword,
"string": self.attrString,
"number": self.attrNumber,
"userType": self.attrUserType,
"comment": self.attrComment,
"preprocessor": self.attrPreprocessor
}
self.SetValue("No file was selected yet!\nPlease select one from the Navigator.")
self.Disable()
def setFile(self, efile):
content = efile.read()
if content is not None:
self.file = efile
self.Enable()
self.SetValue(content)
def onEnter(self, e):
if self.file is None:
return
pos = self.GetInsertionPoint()
code = self.GetValue()
before = code[:pos]
after = code[pos:]
beforeText, afterText = self.file.getMode().getContextualNewline(before, after)
self.WriteText(beforeText)
pos = self.GetInsertionPoint()
self.WriteText(afterText)
self.SetInsertionPoint(pos)
def onUpdate(self, e):
if self.file is None:
e.Skip()
return
code = self.GetValue()
toker = Tokenizer(code)
self.file.getMode().colorize(toker)
self.file.update(code)
# clear the current styles
self.SetStyle(0, self.GetLastPosition(), self.attrNull)
for startPos, endPos, attr in toker.tokens:
self.SetStyle(startPos, endPos, self.attrs[attr])
e.Skip()
setFile()
中的SetValue()
用于触发onUpdate()
事件。现在不是了。而且插入符号也没有出现
有什么建议吗
编辑:以下代码似乎有效:
class MyMCD(wx.Dialog):
def __init__(self, parent, message, caption, choices=[]):
wx.Dialog.__init__(self, parent, -1)
self.SetTitle(caption)
sizer = wx.BoxSizer(wx.VERTICAL)
self.message = wx.StaticText(self, -1, message)
self.clb = wx.CheckListBox(self, -1, choices=choices)
self.chbox = wx.CheckBox(self, -1, 'Select all')
self.btns = self.CreateSeparatedButtonSizer(wx.OK | wx.CANCEL)
#self.Bind(wx.EVT_CHECKBOX, self.EvtChBox, self.chbox)
sizer.Add(self.message, 0, wx.ALL | wx.EXPAND, 5)
sizer.Add(self.clb, 1, wx.ALL | wx.EXPAND, 5)
sizer.Add(self.chbox, 0, wx.ALL | wx.EXPAND, 5)
sizer.Add(self.btns, 0, wx.ALL | wx.EXPAND, 5)
self.SetSizer(sizer)
self.Fit()
这是从一个例子中复制的。然而,我看不出它有什么不同。
(我仍然没有解释丢失的插入符号)。你能安装wxpython演示和/或示例并尝试它们吗?4.0.0的示例似乎可以工作,尽管控制台中仍然有警告,例如
(demo.py:6134):Gtk警告**:21:59:11.723:分配小工具时负内容高度-9(分配1,区段5x5)(节点按钮,所有者GtkButton)
那么,您与演示有什么不同?据我所知,演示中没有自定义对话框。我用找到的工作代码示例编辑了这篇文章。但是,我看不出我的工作有什么不同。