PyQt5 - Application hangs when launching a separate QMainWindow using pynput - python

I'm trying to open a separate window using button combinations in pynput. I'm using the following code to open a new window and hide the original QMainWindow object. When the button is pressed, the logic works perfectly. But when I try to bind the same function to a combination of keyboard input, the application hangs. Anyone knows how I should approach this?
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton, QLabel)
from pynput import keyboard
class Window2(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Window22222")
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "First Window"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
self.pushButton = QPushButton("Start", self)
self.pushButton.move(275, 200)
self.pushButton.setToolTip("<h3>Start the Session</h3>")
self.pushButton.clicked.connect(self.window2)
self.main_window()
def main_window(self):
self.label = QLabel("Manager", self)
self.label.move(285, 175)
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
self.show()
def hotkeys(self):
def on_activate_h():
self.window2()
def for_canonical(f):
return lambda k: f( l.canonical(k) )
h = keyboard.HotKey( keyboard.HotKey.parse( '<ctrl>+<alt>+h' ), on_activate_h )
l = keyboard.Listener( on_press=for_canonical(h.press), on_release=for_canonical(h.release) )
l.start()
def window2(self):
self.w = Window2()
self.w.show()
self.hide()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.hotkeys()
sys.exit(app.exec())

Related

How to use threading in a function to preventing gui from freezing? [duplicate]

This question already has an answer here:
how i can make thread for progress bar with pafy
(1 answer)
Closed 2 years ago.
I'm making a simple audio downloader from video,but whenever i click download button gui stops until downloading has finished.
I thought i can use threading for kind of these things but almost there are hundreds of method to achieve that,but i don't know which one i should choose and that's why I'm so confused then wanted to ask you.
My code here:
import sys
import threading
import pafy
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 button - pythonspot.com'
self.left = 100
self.top = 100
self.width = 320
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
button = QPushButton('Coffee shop radio', self)
button.move(10,10)
button.clicked.connect(self.on_click)
self.show()
def on_click(self):
url = "https://www.youtube.com/watch?v=IcvruhYk0po"
video = pafy.new(url)
bestaudio = video.getbestaudio()
bestaudio.download()
if __name__ == '__main__':
app = QApplication([])
ex = App()
sys.exit(app.exec_())
Have changed the code a little and it works,thanks for everyone.
import sys
import threading
import pafy
from time import sleep
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLineEdit
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
class App(QWidget):
threads = []
def __init__(self):
super().__init__()
self.title = 'YouDio'
self.left = 100
self.top = 100
self.width = 280
self.height = 90
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
button = QPushButton('DOWNLOAD', self)
button.move(10,25)
button.clicked.connect(self.on_click)
self.line = QLineEdit(self)
self.line.move(120,27)
self.show()
def on_click(self):
self.t = threading.Thread(target=self.threaded)
self.t.start()
def threaded(self):
url = self.line.text()
video = pafy.new(url)
bestaudio = video.getbestaudio()
bestaudio.download()
if __name__ == '__main__':
app = QApplication([])
ex = App()
sys.exit(app.exec_())
from threading import Thread
import sys
import threading
import pafy
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot
def download_me():
url = "https://www.youtube.com/watch?v=IcvruhYk0po"
video = pafy.new(url)
bestaudio = video.getbestaudio()
bestaudio.download()
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 button - pythonspot.com'
self.left = 100
self.top = 100
self.width = 320
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
button = QPushButton('Coffee shop radio', self)
button.move(10,10)
button.clicked.connect(self.on_click)
self.show()
def on_click(self):
t = Thread(target=download_me)
t.daemon = True
t.start()
if __name__ == '__main__':
app = QApplication([])
ex = App()
sys.exit(app.exec_())
try this!
In fact download task is done synchronously so your theard will block until the download task is over...you have to put this part of your code inside a daemon thread.
Note: I don't know if python thread can be mixed with Qt so you should use the good Lib but the idea remains the same

How to start multiple instances of function via pyqt5 button?

Hey i wrote an little AutoBuy Bot.
The GUI is made in PYQT5.
I have an button that calls an function with a few parameters.
The problem im running into is, that
the Main Window freezes
with problem nr1 i cant click the button multiple times to trigger the function multiple times.(I want to start it multiple times)
I really need some help with that.
my button :
self.buttonSoleBox = QPushButton('Start Bot', self)
self.buttonBox.move(20, 120)
self.buttonBox.clicked.connect(self.on_click)
and My Button action function:
def on_click(self):
email = self.textbox.text()
password = self.textbox1.text()
aid = self.textbox2.text()
payment = self.textbox4.text()
paypalemail = self.textbox5.text()
paypalpassword = self.textbox6.text()
StartBotFunction(email, password, aid, payment, paypalemail, paypalpassword)
self.textbox.setText("")
self.textbox1.setText("")
self.textbox2.setText("")
self.textbox4.setText("")
self.textbox5.setText("")
self.textbox6.setText("")
for testing:
2files:
main.py
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QLineEdit, QLabel, QComboBox
from PyQt5 import QtGui
from selenium import webdriver
import sys
class App(QMainWindow):
def __init__(self):
super(App,self).__init__()
self.title = 'whatever'
self.left = 200
self.top = 200
self.width = 800
self.height = 500
self.setWindowIcon(QtGui.QIcon('icon.png'))
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.initUI()
def initUI(self):
self.button1 = QPushButton('Start Bot', self)
self.button1.move(20, 120)
self.button1.clicked.connect(self.on_click)
self.show()
def on_click(self):
word = "sneaker"
StartBotFunction(word)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
search.py
from selenium import webdriver
import time
def StartBotFunction(word):
word
driver = webdriver.Chrome()
driver.get('https://www.zalando.de/herren/?q=' + word )
first = driver.find_element_by_xpath('//*[#id="z-nvg-cognac-root"]/div[1]/z-grid/z-grid-item[2]/div/div[5]/z-grid/z-grid-item[1]/div/a')
first.click()
while (driver.page_source).__contains__('Bewertung'):
time.sleep(5)
driver.refresh()
while building that example for you, i found out that i run into my main problem when i do that
if i remove the while thing, i can create as many chromewindows as i click the button
Any idea how to fix that?
while (driver.page_source).__contains__('Bewertung'):
time.sleep(5)
driver.refresh()```
You have to run StartBotFunction in another thread:
import sys
import threading
from PyQt5 import QtCore, QtWidgets
import search
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.lineedit = QtWidgets.QLineEdit("sneaker", placeholderText="word")
button = QtWidgets.QPushButton("Press me")
button.clicked.connect(self.on_click)
flay = QtWidgets.QFormLayout(self)
flay.addRow("Insert word:", self.lineedit)
flay.addRow(button)
#QtCore.pyqtSlot()
def on_click(self):
word = self.lineedit.text()
threading.Thread(target=search.StartBotFunction, args=(word,)).start()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())

Getting value from push button that I can use in a new class/window

I want the first window that opens up to contain 4 push buttons responding to the numbers: 2,3,4,5. Once I have pressed one of these buttons I want the window to close and a new window to open with a label (just so I know it works) and also to use that number as a separate variable as it will select a sheet that I am reading from an excel file.
At the moment I can create the first window with the boxes, and when I press one the new window opens - but I cannot get the selection I made to come across.
Here is as far as I have got so far...
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout, QMainWindow
# select floor window
class select_floor_window(QDialog):
def __init__(self, parent=None):
super().__init__()
self.title = 'Select floor'
self.left = 10
self.top = 10
self.width = 320
self.height = 100
self.selection_ui()
def selection_ui(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.createHorizontalLayout()
windowLayout = QVBoxLayout()
windowLayout.addWidget(self.horizontalGroupBox)
self.setLayout(windowLayout)
self.show()
def createHorizontalLayout(self):
# box layout
self.horizontalGroupBox = QGroupBox("Which floor are you on?")
layout = QHBoxLayout()
# floor buttons
floor_2_button = QPushButton("2", self)
floor_2_button.clicked.connect(self.on_click2)
layout.addWidget(floor_2_button)
floor_3_button = QPushButton("3", self)
floor_3_button.clicked.connect(self.on_click3)
layout.addWidget(floor_3_button)
floor_4_button = QPushButton("4", self)
floor_4_button.clicked.connect(self.on_click4)
layout.addWidget(floor_4_button)
floor_5_button = QPushButton("5", self)
floor_5_button.clicked.connect(self.on_click5)
layout.addWidget(floor_5_button)
self.horizontalGroupBox.setLayout(layout)
# close this window and load main window
def on_click2(self):
self.floorchoice = 2
self.show_main = main_Window()
self.show_main.show()
self.hide()
print("2")
return floorchoice
def on_click3(self):
self.floorchoice = 3
self.show_main = main_Window()
self.show_main.show()
self.hide()
print("3")
return floorchoice
def on_click4(self):
self.floorchoice = 4
self.show_main = main_Window()
self.show_main.show()
self.hide()
print("4")
return floorchoice
def on_click5(self):
self.floorchoice = 5
self.show_main = main_Window()
self.show_main.show()
self.hide()
print("5")
return floorchoice
# create main window
class main_Window(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.title = "2ndwindow"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
show_floor_button = QLabel(floorchoice, self)
show_floor_button.move(100,100)
# Close app button
close_app_button = QPushButton("Exit", self)
close_app_button.move(400,400)
close_app_button.setToolTip("Close application")
close_app_button.clicked.connect(self.CloseApp)
self.InitWindow()
# showing window
def InitWindow(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = select_floor_window()
sys.exit(app.exec_())
Anyway that I try to set up the code, it always says that "name 'floorchoice' is not defined" in the second window, and cannot get it to display the result from the first class.
The functions that are invoked do not return anything, plus self.floorchoice is different floorchoice, the first is an attribute of the class and the other is a local variable.
What you have to do is that the class through the constructor or another method get that information.
In the next one I add one more argument to the invocation using functool.partial, then I pass that argument to the constructor of the other window so that I get that information.
I think your main error is caused by not taking into account that each variable, instance, object, etc. has a scope within the application.
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout, QMainWindow
from functools import partial
# select floor window
class select_floor_window(QDialog):
def __init__(self, parent=None):
super().__init__()
self.title = "Select floor"
self.left = 10
self.top = 10
self.width = 320
self.height = 100
self.selection_ui()
def selection_ui(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.createHorizontalLayout()
windowLayout = QVBoxLayout(self)
windowLayout.addWidget(self.horizontalGroupBox)
def createHorizontalLayout(self):
# box layout
self.horizontalGroupBox = QGroupBox("Which floor are you on?")
layout = QHBoxLayout()
self.horizontalGroupBox.setLayout(layout)
# floor buttons
for option in (2, 3, 4, 5):
button = QPushButton(str(option))
layout.addWidget(button)
wrapper = partial(self.on_click, option)
button.clicked.connect(wrapper)
# close this window and load main window
def on_click(self, option):
self.show_main = main_Window(option)
self.show_main.show()
self.hide()
# create main window
class main_Window(QMainWindow):
def __init__(self, option, parent=None):
super().__init__(parent)
self.title = "2ndwindow"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
show_floor_button = QLabel(str(option), self)
show_floor_button.move(100, 100)
# Close app button
close_app_button = QPushButton("Exit", self)
close_app_button.move(400, 400)
close_app_button.setToolTip("Close application")
close_app_button.clicked.connect(self.close)
self.InitWindow()
# showing window
def InitWindow(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = select_floor_window()
ex.show()
sys.exit(app.exec_())

Open a new window when the button is clicked || PyQt5

I know this question have been asked multiple times. But I can't understand with the existing examples.
I have a code which creates a window with a button called 'start'. I want the app to close the current window and open a new window when the 'start' button is clicked. The new window has to be a blank window.
Any help is much appreciated.
The code is as follows:
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton,
QToolTip, QMessageBox, QLabel
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "First Window"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
self.pushButton = QPushButton("Start", self)
self.pushButton.move(275, 200)
self.pushButton.setToolTip("<h3>Start the Session</h3>")
self.main_window()
def main_window(self):
self.label = QLabel("Manager", self)
self.label.move(285, 175)
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
Try it:
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton,
QToolTip, QMessageBox, QLabel)
class Window2(QMainWindow): # <===
def __init__(self):
super().__init__()
self.setWindowTitle("Window22222")
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "First Window"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
self.pushButton = QPushButton("Start", self)
self.pushButton.move(275, 200)
self.pushButton.setToolTip("<h3>Start the Session</h3>")
self.pushButton.clicked.connect(self.window2) # <===
self.main_window()
def main_window(self):
self.label = QLabel("Manager", self)
self.label.move(285, 175)
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
self.show()
def window2(self): # <===
self.w = Window2()
self.w.show()
self.hide()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())

Creating Custom PyQt5 image-button

I'm trying to create a custom PyQt5 button, but am running across problems displaying it in a QMainWindow object. Here's the code I'm trying:
import sys
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QMainWindow
class PicButton(QAbstractButton):
def __init__(self, pixmap, parent=None):
super(PicButton, self).__init__(parent)
self.pixmap = pixmap
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(event.rect(), self.pixmap)
def sizeHint(self):
return self.pixmap.size()
class App(QMainWindow):
def __init__(self):
super().__init__()
self.left = 0
self.top = 0
self.width = 800
self.height = 800
self.initUI()
def initUI(self):
self.setGeometry(self.left, self.top, self.width, self.height)
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.white)
self.setPalette(p)
btn = PicButton('/home/user/Desktop/Untitled.png')
btn.move(0, 0)
btn.resize(80,80)
self.show()
app = QApplication(sys.argv)
window = App()
The button will work if you just use window = Widget()and put the button object in there as is shown in this answer: how code a Image button in PyQt?
According to your code you must pass a QPixmap to your PicButton, In addition to them if you are going to move it should tell you where, if you pass the parent, it will place in that position relative to the father, but will not be drawn.
To solve the problem you must change:
btn = PicButton('/home/user/Desktop/Untitled.png')
to:
btn = PicButton(QPixmap('/home/user/Desktop/Untitled.png'), self)

Categories

Resources