I am using wxPython to build the GUI for my application. I built the GUI using wxFormBuilder. But when bring the code into my python application, and launch it the window pops up then closes instantly. I am using the XRC for my GUI as well. I am given no error message in the console either while using PyDev with Eclipse.
Python code to launch GUI: http://pastebin.com/jBYWerd9
XRC code: http://pastebin.com/QVEcuX0i
I think you just need
def main():
app = VisualController(redirect=False)
app.MainLoop() #you need this
return #after calling Mainloop you will not get here until your main window is destroyed
The problem is two-fold. As Joran mentioned, you need to actually create an instance of your App class and call the MainLoop() method. The second piece is that you need to actually load the frame from the XRC file and Show it. Change your code to something like this:
import wx
from wx import xrc
class VisualController(wx.App):
def OnInit(self):
self.res = xrc.XmlResource('data/GUI.xrc')
frame = self.res.LoadFrame(None, "MyFrame1")
frame.Show()
return True
def main():
app = VisualController(redirect=False)
app.MainLoop()
if __name__ == '__main__':
main()
If you don't load the frame and show it, then the app doesn't do anything and just exits when it finishes running the OnInit() method. Here are a few links on using XRC:
http://www.blog.pythonlibrary.org/2010/05/11/wxpython-an-introduction-to-xrc/
http://wiki.wxpython.org/XRCTutorial
http://wiki.wxpython.org/UsingXmlResources
Related
I spent longer than I'd care to admit think of a suitable 'question' heading for this topic, as my issue is somewhat hard to articulate.
Here is a quick summary of the situation:
I'm writing a basic GUI with Python 3.4 and PySide
I'm using QFileSystemWatcher to monitor a particular file
When the file is changed, QFileSystemWatcher calls a method, which in turn calls a method within a PySide Class
All of the above seems to be working perfectly, except the GUI-specific actions detailed in the PySide Class method aren't being executed (I'll explain in more detail below).
Example code:
#Establishing the PySide GUI Class
class GUI(QMainWindow, Ui_GUI):
def __init__(self, parent=None)
super(GUI, self).__init__(parent)
self.setupUi(self)
QtCore.QObject.connect(self.Button, QtCore.SIGNAL("clicked()"), self.Run)
def Run(self):
print("1")
self.treeWidget1.clear()
self.treeWidget2.clear()
print("2")
self.label1.setText("Text 1")
self.label2.setText("Text 2")
print("3")
for y in range(0, 5):
self.treeWidget1.resizeColumnsToContents()
print("Finished")
#Establish the file monitoring mechanism, *outside* the PySide class
def FileChanged():
Script = GUI()
Script.Run()
Paths = ['path/to/file']
Watch = QtCore.QFileSystemWatcher(Paths)
Watch.fileChanged.connect(FileChanged)
#Setting up the GUI
if __name__ == '__main__':
app = QApplication(sys.argv)
showGUI = GUI()
showGUI.show()
app.exec_()
As I mentioned above, the above code doesn't return any errors. When I change the file (listed in the path), FileChanged does indeed call the Run() method from the GUI class. However, it won't actually do any of the 'stuff', it will only execute the print commands in between the 'stuff'.
If I then click on the 'Button' in the GUI, it will execute Run() correctly, and properly execute all the 'stuff'.
My question: is there something I'm missing here? If it's calling the method correctly, and is able to execute the various 'print' commands, why is it not executing the actual 'stuff'?
Thanks!
EDIT 1: I've removed the -do stuff- tags and put in some example code. All the 'stuff' code relates to updating various PySide QLabels, QTreeWidgets, etc.
EDIT 2: I forget the () at the end of the treeWidget clear commands.
The Script object created in the FileChanged function has local scope, and will be garbage-collected as soon as the function returns.
If the Run slot gets called when the signal fires, it will carry out all of the changes correctly, but you won't get to see any of those changes, because Script will be deleted before it is ever shown.
In order to for the example script to begin to make any sense, it would need to be re-arranged to something like this:
#Setting up the GUI
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
showGUI = GUI()
#Establish the file monitoring mechanism, *outside* the PySide class
def FileChanged():
showGUI.Run()
Paths = ['path/to/file']
Watch = QtCore.QFileSystemWatcher(Paths)
Watch.fileChanged.connect(FileChanged)
showGUI.show()
app.exec_()
Of course, it's possible that your real code is nothing like the example in your question (which has numerous other errors preventing it from being run), and so this might be no help. But if that is the case, you will have to post a fully working, self-contained example that properly demonstrates the problems you are having.
i have a strange problem. I created a GUI program which runs in "spyder" with WinPython-64bit-3.3.2.3 with no problems, now i want to run it without the console to pop up and i try to use pythonw.exe.
When i save my GUI as gui.pyw i can open it with PythonWin by right clicking and use edit with PythonWin but simply double-clicking will make my GUI pop up for less than a second and exit the program afterwards.
Does this have to do with my GUI programming?
the "structure" is this one:
import sys
from PyQt4 import QtGui, QtCore, Qt
from Main_Window_v2 import Ui_Dialog as Dlg
class MeinDialog(QtGui.QDialog, Dlg):
def __init__(self):
QtGui.QDialog.__init__(self)
self.setupUi(self)
self.connect(self.buttonOK,
QtCore.SIGNAL("clicked()"), self.onOK)
self.connect(self.buttonAbbrechen,
QtCore.SIGNAL("clicked()"), self.onClose)
self.connect(self.buttonsql,
QtCore.SIGNAL("clicked()"), self.onsql)
def onsql(self):
login=self.login_text_box.toPlainText()
from calc import get_variables #sql query
self.get_variables=get_variables(login)
#calls a class´ __init__ in another file in my direcotry
def onOK(self):
login=self.login_text_box.toPlainText()
self.get_variables.plot(login)
#calls another function in my class "calc"
def onClose(self):
print("bye!")
self.close()
app = QtGui.QApplication(sys.argv)
dialog = MeinDialog()
dialog.show()
I also tried to get an .exe using cx_freeze and after trying to making build as described here Cx_Freeze: I have the same problem: The Main-Window of the GUI
pops up and disappears again
Just add app.exec_() at the end of your code. Your code was running well in Spyder because Spyder uses PyQt and had the main loop of events already running.
You should add app.exex_() at the end of your code, it is used to dispatch all PyQt GUI threads message or other threads info message.
I've just begun using pyqt4. I followed a tutorial (http://zetcode.com/tutorials/pyqt4/)
One thing that puzzles me is this part:
def main():
app = QtGui.QApplication(sys.argv)
ex = GUI()
sys.exit(app.exec())
And the reason for this I explain here:
I have made a small program that opens four more windows except for the first main window.
So I tried to replicate what I saw worked with main-window and created a class for every new window and tried to do like with the above. Currently it looks like this:
def main2():
#app = QtGui.QApplication(sys.argv)
ex2 = Settings()
sys.exit(app.exec())
As you can see I have modified it. If I left the first line in the function uncommented the program would crash. I tried to do without the sys.exit(app.exec_())-part but that would only make the new window close milliseconds after it showed.
This way though, everything runs and works. Only that in the command window, an error message displays. I don't know how to fix this, since I cannot remove the last line, and I dont't know what to replace "app" with.
I know I'm probably doing the new windows wrong from the beginning, but I don't know how to make these windows open from the original window in any other way. I haven't been able to get anything else to work, and this at least runs and works right now. So the only problem is error messages in the prompt, it would be nice to get rid of them :)
Thanks for any help (complicated and easy ones)!
Forgot to mention, I made the classes start like this:
class GUI(QtGui.QMainWindow):
def __init__(self):
super(GUI, self).__init__()
self.initUI()
and
class Settings(QtGui.QWidget):
def __init__(self):
super(Settings, self).__init__()
...here goes some more...
self.initUI2()
and I open Settings-window by calling main2()
You must create one and only one QApplication in your program.
Keep in mind that GUI programming is event-driven, you first declare widgets and then run the main loop with app.exec(), when the user quit your application, app.exec() returns.
The QApplication purpose is to handle user events and propagate them to your code with Qt signals. I suggest you check Qt documentation, it's very complete, even if it's targetting C++ programmers.
So for instance, a way to create two widgets would be:
def main():
app = QtGui.QApplication(sys.argv)
ex = QtGui.QWidget()
ex.show()
ex2 = QtGui.QWidget()
ex2.show()
sys.exit(app.exec())
I am experiencing different behaviour on the same code using the python console and a python script.
The code is as follows:
import gtk
import webkit
win = gtk.Window()
win.show()
web = webkit.WebView()
win.add(web)
web.show()
web.open("http://www.google.com")
When running the code in the python console, the output is a new frame that contains the google main page.
When running the code as a script, the result is a void frame. It closes very fast but even if I use a delay function, the webkit is not added to the frame.
How is it possible?
Furthermore, using PyDev IDE it flags: "unresolved import: gtk",
but if i run the project, the program starts without problem of compilation. is it normal?
Add
gtk.main()
to the end of your script. This starts the gtk event loop.
import gtk
import webkit
class App(object):
def __init__(self):
win = gtk.Window()
win.connect("destroy", self.destroy)
web = webkit.WebView()
web.open("http://www.google.com")
win.add(web)
web.show()
win.show()
def destroy(self, widget, data = None):
gtk.main_quit()
app = App()
gtk.main()
My guess is that the console keeps the python session open, while at the end of the script the program closes. When the script closes, it takes everything it created with it.
Something to test this theory: if you type "exit" in the console do you see the interface shut down in the same manner? If so, think of some code (e.g. a pause like a raw_input) that will allow the script to stay open.
Good luck!
Lets say I have this sample code:
import wx
app = wx.App(False) # Create a new app, don't redirect stdout/stderr to a window.
frame = wx.Frame(None, wx.ID_ANY, "Hello World") # A Frame is a top-level window.
s=wx.Button(frame,-1,"New")
frame.Show(True) # Show the frame.
app.MainLoop()
Like in some programs, if you press the New button, it will open the program again in another window. I am wondering, how can i do this in python?
I cannot make a window object then make copies of it because, in my actual program I am using global variables and these global variables are made for only one window.
It appears that my only option is to find a way to run the program again.
You could try something like this
import subprocess
import sys
new_process = subprocess.Popen([sys.executable]+sys.argv)
Which will run python again with the arguments it was run with originally. Or modifying your original example to make pressing the button run the script again :-
import wx
import subprocess
import sys
def re_run(e):
new_process = subprocess.Popen([sys.executable]+sys.argv)
app = wx.App(False) # Create a new app, don't redirect stdout/stderr to a window.
frame = wx.Frame(None, wx.ID_ANY, "Hello World") # A Frame is a top-level window.
s=wx.Button(frame,-1,"New")
s.Bind(wx.EVT_BUTTON, re_run)
frame.Show(True) # Show the frame.
app.MainLoop()