I try to make a download interface via tkinter. The following code works well in Pycharm. But when I try to make it an exe file using pyinstaller, it opens a new window every time I click on button1(the download button), which is undesired. Could you please tell me how to fix it? I'm working on Win10. Thanks in advance.
import tkinter as tk
from download import download_yv as dyv
import multiprocessing
class DownloadPage(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.grid()
self.download_flag=True
self.current_row=0
self.current_rowspan=0
self.label1=tk.Label(self,text='Url:',)
self.label1.grid(row=self.current_row,column=0,)
self.text1=tk.Entry(self,width=45)
self.text1.grid(row=self.current_row,column=1,padx=0,pady=0)
self.current_row+=1
self.label2=tk.Label(self,text='Save_Dir:',wraplength=200,)
self.label2.grid(row=self.current_row,column=0)
self.text2=tk.Entry(self,width=45)
self.text2.grid(row=self.current_row,column=1,padx=0,pady=0,)
self.current_row+=1
self.label3=tk.Label(self,text='Overwrite:',)
self.label3.grid(row=self.current_row,column=0)
self.var1=tk.BooleanVar(self)
self.var1.set('False')
self.menu1=tk.OptionMenu(self,self.var1,'True','False')
self.current_rowspan=2
self.menu1.grid(row=self.current_row,column=1,columnspan=2,rowspan=self.current_rowspan,sticky='news')
self.current_row+=self.current_rowspan
self.label4=tk.Label(self,text='Categorize:')
self.label4.grid(row=self.current_row,column=0)
self.var2 = tk.BooleanVar(self)
self.var2.set(True)
self.menu2=tk.OptionMenu(self,self.var2,'True','False')
self.menu2.grid(row=self.current_row,column=1,columnspan=2,rowspan=self.current_rowspan,sticky='news')
self.current_row+=self.current_rowspan
self.current_rowspan=2
self.button1=tk.Button(self,text='download',command=self.download)
self.button1.grid(row=self.current_row,column=1,columnspan=2,rowspan=self.current_rowspan,sticky='news')
self.current_row+=self.current_rowspan
self.button2=tk.Button(self,text='Stop Downloading',command=self.stop_download)
self.button2.grid(row=self.current_row,column=1,columnspan=1,)
def download(self):
var1=self.var1.get()
var2=self.var2.get()
# print(var1,type(var1),var2,type(var2))
self.download_process=multiprocessing.Process(target=dyv,args=(self.text1.get(),self.text2.get(),var1,var2))
self.download_process.start()
def stop_download(self):
if self.download_process and self.download_process.is_alive():
self.download_process.terminate()
if __name__ == '__main__':
root=tk.Tk()
app=DownloadPage(root)
app.mainloop()
Related
I am working on tkinter project. While double clicking the python file, the py.exe file is visible in the background which doesn't look good. so is there a way to make the py.exe invisible or resize it.Please help me with your ideas. Thank you
Sample code:
import tkinter.messagebox
from tkinter import ttk
class Demo1:
data = []
def __init__(self, master):
self.master = master
self.label=tkinter.Label(text="Add IP/Hostname")
self.label.pack()
self.t=tkinter.Text(self.master,height=20,width=50)
self.t.pack()
self.button = tkinter.Button(self.master,height=3,width=10, text="OK"
)
self.button.pack()
def main():
root = tkinter.Tk()
app = Demo1(root)
root.mainloop()
if __name__ == '__main__':
main()
Change the .py extension to .pyw. That should suppress the console window.
Note: the .pyw extension should be associated to be opened with pythonw.exe. Normally this is done by the Python installer. If not, select pythonw.exe the first time you click on a .pyw file. That will make the proper association.
Does that work?
import ctypes
ctypes.windll.user64.ShowWindow(ctypes.windll.kernel64.GetConsoleWindow(), 6 )
Otherwise please post an example code.
I'm trying to create an application that contains a web browser within it, but when I add the web browser my menu bar visually disappears but functionally remains in place. The following are two images, one showing the "self.centralWidget(self.web_widget)" commented out, and the other allows that line to run. If you run the example code, you will also see that while visually the entire web page appears as if the menu bar wasn't present, you have to click slightly below each entry field and button in order to activate it, behaving as if the menu bar was in fact present.
Web Widget Commented Out
Web Widget Active
Example Code
import os
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
class WebPage(QWebEngineView):
def __init__(self, parent=None):
QWebEngineView.__init__(self)
self.current_url = ''
self.load(QUrl("https://facebook.com"))
self.loadFinished.connect(self._on_load_finished)
def _on_load_finished(self):
print("Url Loaded")
class MainWindow(QMainWindow):
def __init__(self, parent=None):
# Initialize the Main Window
super(MainWindow, self).__init__(parent)
self.create_menu()
self.add_web_widet()
self.show()
def create_menu(self):
''' Creates the Main Menu '''
self.main_menu = self.menuBar()
self.main_menu_actions = {}
self.file_menu = self.main_menu.addMenu("Example File Menu")
self.file_menu.addAction(QAction("Testing Testing", self))
def add_web_widet(self):
self.web_widget = WebPage(self)
self.setCentralWidget(self.web_widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.showMaximized()
sys.exit(app.exec_()) # only need one app, one running event loop
Development Environment
Windows 10, PyQt5, pyqt5-5.9
EDIT
The problem doesn't seem to be directly related to the menu bar. Even removing the menu bar the issue still occurs. That said, changing from showMaximized() to showFullScreen() does seem to solve the problem.
I no longer believe this is an issue with PyQt5 specifically but rather a problem with the graphics driver. Specifically, if you look at Atlassian's HipChat application it has a similar problem which is documented here:
https://jira.atlassian.com/browse/HCPUB-3177
Some individuals were able to solve the problem by running the application from the command prompt with the addendum "--disable-gpu" but that didn't work for my python application. On the other hand, rolling back the Intel(R) HD Graphics Driver did solve my problem. Version 21.20.16.4627 is the one that seems to be causing problems.
Im new to programming, and really only doing this for a school project. Im trying to make a GUI that has a series of buttons that when pressed will run a specific emulator. When I try to run this I get a error saying "z26" is undefined. Im not quite sure on how to actually define it.
from tkinter import *
import os
class Application(Frame):
def __init__(self, master):
Frame.__init__(self,master)
self.grid()
self.create_widgets()
def create_widgets(self):
self._button = Button(self, text = "Atari", command = self._openFile)
self._button.grid()
def _openFile(self):
os.startfile(z26.exe)
root = Tk()
root.title("Arcade")
root.geometry("200x85")
app = Application(root)
root.mainloop()
The problem is that you are using x26.exe as a literal, and it is getting evaluated as though it were part of the Python program itself.
Instead, put the path with quotequotations, to make it a string:
os.startfile('path/z26.exe')
See also the Python documentation for os.startfile(path[, operation]).
I have a main tkinter window that can take up to a few seconds to load properly. Because of this, I wish to have a splash screen that shows until the init method of the main class has finished, and the main tkinter application can be shown. How can this be achieved?
Splash screen code:
from Tkinter import *
from PIL import Image, ImageTk
import ttk
class DemoSplashScreen:
def __init__(self, parent):
self.parent = parent
self.aturSplash()
self.aturWindow()
def aturSplash(self):
self.gambar = Image.open('../output5.png')
self.imgSplash = ImageTk.PhotoImage(self.gambar)
def aturWindow(self):
lebar, tinggi = self.gambar.size
setengahLebar = (self.parent.winfo_screenwidth()-lebar)//2
setengahTinggi = (self.parent.winfo_screenheight()-tinggi)//2
self.parent.geometry("%ix%i+%i+%i" %(lebar, tinggi, setengahLebar,setengahTinggi))
Label(self.parent, image=self.imgSplash).pack()
if __name__ == '__main__':
root = Tk()
root.overrideredirect(True)
progressbar = ttk.Progressbar(orient=HORIZONTAL, length=10000, mode='determinate')
progressbar.pack(side="bottom")
app = DemoSplashScreen(root)
progressbar.start()
root.after(6010, root.destroy)
root.mainloop()
Main tkinter window minimum working example:
import tkinter as tk
root = tk.Tk()
class Controller(tk.Frame):
def __init__(self, parent):
'''Initialises basic variables and GUI elements.'''
frame = tk.Frame.__init__(self, parent,relief=tk.GROOVE,width=100,height=100,bd=1)
control = Controller(root)
control.pack()
root.mainloop()
EDIT: I can use the main window until it has finished loading using the .withdraw() and .deiconify() methods. However my problem is that I cannot find a way to have the splash screen running in the period between these two method calls.
a simple example for python3:
#!python3
import tkinter as tk
import time
class Splash(tk.Toplevel):
def __init__(self, parent):
tk.Toplevel.__init__(self, parent)
self.title("Splash")
## required to make window show before the program gets to the mainloop
self.update()
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.withdraw()
splash = Splash(self)
## setup stuff goes here
self.title("Main Window")
## simulate a delay while loading
time.sleep(6)
## finished loading so destroy splash
splash.destroy()
## show window again
self.deiconify()
if __name__ == "__main__":
app = App()
app.mainloop()
one of the reasons things like this are difficult in tkinter is that windows are only updated when the program isn't running particular functions and so reaches the mainloop. for simple things like this you can use the update or update_idletasks commands to make it show/update, however if the delay is too long then on windows the window can become "unresponsive"
one way around this is to put multiple update or update_idletasks command throughout your loading routine, or alternatively use threading.
however if you use threading i would suggest that instead of putting the splash into its own thread (probably easier to implement) you would be better served putting the loading tasks into its own thread, keeping worker threads and GUI threads separate, as this tends to give a smoother user experience.
I have been looking for a way to display a right-click popup menu on OSX.
So far all of my attempts have been unsuccessful. The same code will work fine on a Linux VM(Ubuntu).
For arguments sake I copied the code written in these two pages and tried to run them on my machine.
tkinter app adding a right click context menu?
http://effbot.org/zone/tkinter-popup-menu.htm
Neither have worked in the way I expect them to on OSX but they do when I run them on an Ubuntu VM.
The machine I am using is a Mac Mini4,1 running OSX 10.6.8.
Has anyone else experienced this and is there a viable workaround?
For odd historical reasons, the right button is button 2 on the Mac, but 3 on unix and windows.
Here is an example that works on my OSX box:
try:
# python 2.x
import Tkinter as tk
except ImportError:
# python 3.x
import tkinter as tk
class Example(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
self.popupMenu = tk.Menu(self, tearoff=0)
self.popupMenu.add_command(label="One", command=self.menu_one)
self.popupMenu.add_command(label="Two", command=self.menu_two)
self.popupMenu.add_command(label="Three", command=self.menu_three)
self.bind("<Button-2>", self.popup)
def menu_one(self):
print "one..."
def menu_two(self):
print "two..."
def menu_three(self):
print "three..."
def popup(self, event):
self.popupMenu.post(event.x_root, event.y_root)
if __name__ == "__main__":
root =tk.Tk()
frame = Example(root, width=200, height=200)
frame.pack(fill="both", expand=True)
root.mainloop()
Because of the MacOS's mouse button index is different from Windows or Linux .You can try this in your code:
MAC_OS = False
if sys.platform == 'darwin':
MAC_OS = True
if MAC_OS:
self.bind('<Button-2>', self.context_popup)
else:
self.bind('<Button-3>', self.context_popup)