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()
Related
I am wondering on how I can create a restart button that once clicked, can restart the entire script. What I thought was that you destroy the window then un-destroy it but apparently there is no un-destroy function.
I found a way of doing it for a generic python program on this website: https://www.daniweb.com/programming/software-development/code/260268/restart-your-python-program. I wrote an example with a basic tkinter GUI to test it:
import sys
import os
from tkinter import Tk, Label, Button
def restart_program():
"""Restarts the current program.
Note: this function does not return. Any cleanup action (like
saving data) must be done before calling this function."""
python = sys.executable
os.execl(python, python, * sys.argv)
root = Tk()
Label(root, text="Hello World!").pack()
Button(root, text="Restart", command=restart_program).pack()
root.mainloop()
The following solution works as well but is quite harsh, i.e. the entire environment is lost.
# kills the whole application and starts a fresh one
def restart():
root.destroy()
root = Tk()
root.mainloop()
I would Like to Use this Function:-
First of All Import os Module
import os
Then Use this Code:-
# Restarts the Whole Window
def restart():
root.destroy()
os.startfile("main.py")
Or if You want no console behind then Simply Change the extension of the file to .pyw
And Run this Code:-
# Restarts the Whole Window
def restart():
root.destroy()
os.startfile("main.pyw")
I am running a wxPython application that does a lot of modules and packages importing at the beginning and gathering information about the computer (network interfaces, internet connection..) so it takes time, and I'm showing a logo in that time until it ends. the problem is that the logo crashes if you press on it (because the importing are on the MainThread and the GUI can't respond to events), How can I show a logo while importing without letting the GUI crash? (I don't want to let the user to click on the Logo anyway)
Inspired by Tim Roberts in this wxPython-users thread I first tried to spin off the splash screen in a separate thread, which did not work (wxwidgets complains it it not in the main thread). So I did the only obvious thing which I should have done in the first place: make the long running at startup a separate thread.
Side effect: As the splash screens now can react to events, it will disappear when clicked on.
import wx
class long_running(object):
def __init__(self):
bitmap = wx.EmptyBitmap(300, 150, 127)
self.mainframe = wx.Frame(None, -1, 'mainframe')
self.splash = wx.SplashScreen(bitmap, wx.SPLASH_TIMEOUT, 20000, self.mainframe)
def start(self):
import time
# mimicking something taking very long time on startup
for i in range(20):
time.sleep(0.5)
print i
wx.CallAfter(self.continue_)
def continue_(self):
#Destroy the splash screen.
if self.splash:
self.splash.Hide()
# self.splash.Destroy()
self.mainframe.Show()
if __name__ == '__main__':
import thread
app = wx.App()
long_rnn = long_running()
# Begin loading the application.
thread.start_new_thread(long_rnn.start, ())
# Application loaded.
app.MainLoop()
In a recent project (on Windows7 and wxPython 2.9.5.1): For displaying a wx.SplashScreen while modules are importing we did the following:
We have a main module, which does import wx in the beginning, create the wx.App and display the splash screen. Only after showing the splash screen we begin to import the "heavy" modules. The very first startup will take 40 seconds. In fact the app will crash if the user clicks on the splash screen. Better said, Windows displays a message box (EDIT2) with "Python.exe has stopped working." If the user clicks "Terminate" the app will in fact terminate/crash. If the user does nothing, the app will start up normally. So on Windows there is no "real" crash. It will also not happen when starting the second time (because things are cached)? On subsequent starts startup time is 5 seconds. Sorry, no real answer but too long for a comment also.
EDIT: Minimum working example added: Click every one or two seconds on the splash while it is displayed to make Windows show the "Python has stopped working" dialog. The dialog will simply go away when long_running() has returned.
# -*- coding: utf-8 -*-
def long_running():
import time
time.sleep(10)
# does not show "Python ... stopped working ..."
#for _ in range(20):
# time.sleep(0.5)
# wx.Yield()
if __name__ == '__main__':
import wx
app = wx.App()
bitmap = wx.EmptyBitmap(300, 150, 127)
splash = wx.SplashScreen(bitmap, wx.SPLASH_TIMEOUT, 20000, None)
# Begin loading the application.
long_running()
# Application loaded.
#Destroy the splash screen.
splash.Hide()
splash.Destroy()
app.MainLoop()
I have a notebook whose parent is the main frame of the application. The main frame also has a panel showing a chart to the side of the notebook, a menu bar and a status bar.
The notebook has a couple of pages and each page has some nested panels.
I'd like the callbacks for buttons in those panels to be able to talk to the main frame.
At the moment, that means a ridiculous chain of 'parents'. For example, to get to status bar from a panel on a notebook page I would do:
stat = self.parent.parent.parent.status_bar
The first parent is the notebook page, the second parent is the notebook and finally the last parent is the main frame.
This leads to very obtuse code...
Naturally you can see how this might get worse if I wanted to talk between elements on the panel adjacent to the notebook or nest the notebook in it's own panel..
Any tips?
There is a simple way to get your Main Frame.
Since you can get your app instance anywhere in your code with "wx.GetApp()", then you can set your Mainframe into your app instance, it would be easy to fecth.
Please try following simple sample:
import wx
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
btn = wx.Button(wx.Panel(self), label = "test")
self.Bind(wx.EVT_BUTTON, self.onButton)
def onButton(self, evt):
print "onButton"
app = wx.GetApp()
print app.Myframe
app = wx.App()
frame = TestFrame()
frame.Center()
frame.Show()
app.Myframe = frame
app.MainLoop()
If you need to get access to the top frame, you should be able to use wx.GetTopLevelParent(). Personally, I think pubsub is probably the easiest way to call various classes in wxPython and it's pretty clean too. Plus if you need to call multiple frames or panels or whatever, you can have them all "subscribe" to the same message name and then publish a message for all of them to pick up.
Here's a tutorial for pubsub: http://www.blog.pythonlibrary.org/2013/09/05/wxpython-2-9-and-the-newer-pubsub-api-a-simple-tutorial/
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
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!