pyqt5 form and outer module exchange data - python

I have a Pyqt5 form where the user enters data. This data is sent to another module, where it is processed and returned for display in the form.
Very simplistically it looks like this:
frm.py
import sys
from PyQt5.QtWidgets import *
import mdl
def fnc0(in_val):
mdl.fnc1(in_val)
def fnc2(rezult):
msg.setText(rezult)
app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout()
btn = QPushButton('button')
btn.clicked.connect(lambda: fnc0(5))
layout.addWidget(btn)
msg = QLabel('')
layout.addWidget(msg)
window.setLayout(layout)
window.show()
sys.exit(app.exec_())
mdl.py
import frm
def fnc1(in_val):
out_val = str(in_val*2)
frm.fnc2(out_val)
However, when doing this, I get the error of using circular modules:
AttributeError: partially initialized module 'mdl' has no attribute 'fnc1' (most likely due to a circular import)
Is it possible to process the data sent from the form to another module, and then return the result to the form?

A possible solution is that in a third file we create a logic where we can register functions that receive the result and a function that invokes those functions:
core.py
_funct = []
def register_writer(func):
_funct.append(func)
return func
def write(text):
for f in _funct:
f(text)
mdl.py
import core
def fnc1(in_val):
out_val = str(in_val * 2)
core.write(out_val)
frm.py
import sys
from PyQt5.QtWidgets import *
import core
import mdl
#core.register_writer
def fnc2(rezult):
msg.setText(rezult)
app = QApplication(sys.argv)
window = QWidget()
layout = QVBoxLayout()
btn = QPushButton("button")
btn.clicked.connect(lambda: mdl.fnc1(5))
layout.addWidget(btn)
msg = QLabel()
layout.addWidget(msg)
window.setLayout(layout)
window.show()
sys.exit(app.exec_())

Related

Qaction Shortcut in extended contextmenu not triggered

I try to extend the contextmenu of a QLineEdit with an additional entry for replacing text. I can extend the contextmenu with .createStandardContextMenu(), which works fine. But when I try to add a shortcut with .setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R)) it will not react on the key. Same with different keys, which I tried. In addition the shortcut made with QAction('&Replace', self) doesn't work too.
Some examples here in SO and other sources are constructed in the same way, so I'm wondering that nobody else has got the same problem. Seems that I'm missing anything. But what? I can't figure out, checked the docs multiple times.
Working Example:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
class ECM(QWidget):
def __init__(self):
super(ECM, self).__init__()
self.setWindowTitle("Extended Context Menu")
self.lineEdit = QLineEdit()
self.lineEdit.setContextMenuPolicy(Qt.CustomContextMenu)
self.lineEdit.customContextMenuRequested.connect(self.my_contextMenuEvent)
layout = QVBoxLayout()
layout.addWidget(self.lineEdit)
self.setLayout(layout)
self.setFixedSize(800,200)
self.show()
def replace(self):
print("replace")
def my_contextMenuEvent(self):
print("my_contextMenuEvent")
menu = self.lineEdit.createStandardContextMenu()
action = QAction('&Replace', self)
action.setStatusTip('Replace values')
action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
action.triggered.connect(self.replace)
menu.addAction(action)
menu.exec_()
if __name__ == '__main__':
app = QApplication(sys.argv)
sender = ECM()
app.exec_()
Based on musicamante's comment I came to the following solution:
Extract from the docs:
If you want to extend the standard context menu, reimplement this
function, call createStandardContextMenu() and extend the menu
returned.
The default use of the QAction list (as returned by actions()) is to
create a context QMenu.
It's not totally logically to me, not for the 1st time ;-)
Final code:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
class ECM(QWidget):
def __init__(self):
super(ECM, self).__init__()
self.setWindowTitle("Extended Context Menu")
self.lineEdit = QLineEdit()
self.lineEdit.setContextMenuPolicy(Qt.CustomContextMenu)
self.lineEdit.customContextMenuRequested.connect(self.my_contextMenuEvent)
layout = QVBoxLayout()
layout.addWidget(self.lineEdit)
self.setLayout(layout)
self.setFixedSize(800,200)
action = QAction('&Replace', self)
action.setStatusTip('Replace values')
action.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_R))
action.triggered.connect(self.replace)
self.lineEdit.addAction(action)
self.show()
def replace(self):
print("replace")
def my_contextMenuEvent(self):
menu = self.lineEdit.createStandardContextMenu()
menu.addActions(self.lineEdit.actions())
menu.exec_()
if __name__ == '__main__':
app = QApplication(sys.argv)
sender = ECM()
app.exec_()

The layout is incorrect after remove widget

I am implement my project using pyqt5. Currently, I have a window including many widget. Now, I want to remove some widgets. The window looks like:
Now, I want to remove the 'name1' widget including the QLabel and QPushButton.
However, after removing all 'name1' widgets, the 'name2' widgets including QLabel and QPushButton can not self-adapte with the window, like:
All my code is:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class Window(QDialog):
def __init__(self):
super().__init__()
self.initGUI()
self.show()
def initGUI(self):
layout = QVBoxLayout()
self.setLayout(layout)
removeLayout = QHBoxLayout()
self.__removeText = QLineEdit()
self.__removeBtn = QPushButton('Remove')
self.__removeBtn.clicked.connect(self.remove)
removeLayout.addWidget(self.__removeText)
removeLayout.addWidget(self.__removeBtn)
ROIsLayout = QVBoxLayout()
for name in ['name1', 'name2']:
subLayout = QHBoxLayout()
subText = QLabel(name)
subText.setObjectName(name)
subBtn = QPushButton(name)
subBtn.setObjectName(name)
subLayout.addWidget(subText)
subLayout.addWidget(subBtn)
ROIsLayout.addLayout(subLayout)
layout.addLayout(removeLayout)
layout.addLayout(ROIsLayout)
self.__ROIsLayout = ROIsLayout
def remove(self, checked=False):
name = self.__removeText.text()
while True:
child = self.__ROIsLayout.takeAt(0)
if child == None:
break
while True:
subChild = child.takeAt(0)
if subChild == None:
break
obName = subChild.widget().objectName()
if name == obName:
widget = subChild.widget()
widget.setParent(None)
child.removeWidget(widget)
self.__ROIsLayout.removeWidget(widget)
del widget
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
update:
Actually, the issue may be the takeAt. The following code is workable:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class Window(QDialog):
def __init__(self):
super().__init__()
self.initGUI()
self.show()
def initGUI(self):
layout = QVBoxLayout()
self.setLayout(layout)
removeLayout = QHBoxLayout()
self.__removeText = QLineEdit()
self.__removeBtn = QPushButton('Remove')
self.__removeBtn.clicked.connect(self.remove)
removeLayout.addWidget(self.__removeText)
removeLayout.addWidget(self.__removeBtn)
ROIsLayout = QVBoxLayout()
for name in ['name1', 'name2']:
subLayout = QHBoxLayout()
subLayout.setObjectName(name)
subText = QLabel(name, parent=self)
subText.setObjectName(name)
subBtn = QPushButton(name, parent=self)
subBtn.setObjectName(name)
subLayout.addWidget(subText)
subLayout.addWidget(subBtn)
ROIsLayout.addLayout(subLayout)
print(name, subLayout, subText, subBtn)
layout.addLayout(removeLayout)
layout.addLayout(ROIsLayout)
self.__ROIsLayout = ROIsLayout
self.record = [subLayout, subText, subBtn]
def remove(self, checked=False):
layout = self.record[0]
txt = self.record[1]
btn = self.record[2]
layout.removeWidget(txt)
txt.setParent(None)
txt.deleteLater()
layout.removeWidget(btn)
btn.setParent(None)
btn.deleteLater()
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
But, I have printed the QLabel/QPushButton in the self.record, and I find it is the same with that from child.takeAt(0).widget().
The main issue in your code is that you're constantly using takeAt(). The result is that all items in the __ROIsLayout layout will be removed from it (but not deleted), which, in your case, are the sub layouts. This is clearly not a good approach: only the widgets with the corresponding object name will be actually deleted, while the others will still be "owned" by their previous parent, will still be visible at their previous position and their geometries won't be updated since they're not managed by the layout anymore.
There are multiple solutions to your question, all depending on your needs.
If you need to remove rows from a layout, I'd consider setting the object name on the layout instead, and look for it using self.findChild().
Also consider that, while Qt allows setting the same object name for more than one object, that's not suggested.
Finally, while using del is normally enough, it's usually better to call deleteLater() for all Qt objects, which ensures that Qt correctly removes all objects (and related parentship/connections).
Another possibility, for this specific case, is to use a QFormLayout.

Switch widget in QStackWidget from a button in another file

I got two py files. One has the main window with a QStackedWidget inside, the setCurrentWidget is set according to a condition. The other file has a widget which is dynamically added into the stacked widget and set as current widget when a button in the main window is clicked.
The widget in the second file has a dialog with a button in it. What I'm trying to do is, on clicking the button inside the dialog, the dialog should be closed and the setCurrentWidget is set according to the condition and the widget is removed from the stacked widget.
Here is what I've tried:
mainwindow.py
import sys
import os
import pathlib
from PySide2.QtWidgets import *
from PySide2 import *
from PySide2.QtCore import *
from PySide2.QtGui import *
list1 = ["item1", "item2", "item3"]
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.resize(400, 300)
self.toolbar = QWidget()
self.toolbar.setFixedHeight(30)
self.toolbar.setStyleSheet("background: grey;")
self.button = QPushButton("Click here!")
t_layout = QHBoxLayout()
t_layout.setMargin(0)
t_layout.addWidget(self.button)
self.toolbar.setLayout(t_layout)
self.p1_label = QLabel("Such empty!")
self.p1_label.setStyleSheet("font-size: 30px;")
self.p1_label.setAlignment(Qt.AlignCenter)
self.p2_widget = QWidget()
self.p2_widget.setStyleSheet("background: orange;")
self.sw = QStackedWidget()
self.sw.addWidget(self.p1_label)
self.sw.addWidget(self.p2_widget)
if not list1:
self.sw.setCurrentWidget(self.p1_label)
else:
self.sw.setCurrentWidget(self.p2_widget)
self.mw_layout = QVBoxLayout()
self.mw_layout.addWidget(self.toolbar)
self.mw_layout.addWidget(self.sw)
self.setLayout(self.mw_layout)
def switch_widget():
import widget_test
p3 = widget_test.widget()
self.sw.addWidget(p3)
self.sw.setCurrentWidget(p3)
self.button.clicked.connect(switch_widget)
def switch_back(self):
import widget_test
p3 = widget_test.widget()
mwin = MainWindow()
sw_ = mwin.sw
sw_.removeWidget(p3)
p1 = mwin.p1_label
p2 = mwin.p2_widget
if not list1:
sw_.setCurrentWidget(p1)
else:
sw_.setCurrentWidget(p2)
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
widget.py
import sys
import os
import pathlib
import datetime
from PySide2.QtWidgets import *
from PySide2 import *
from PySide2.QtCore import *
from PySide2.QtGui import *
class widget(QWidget):
def __init__(self):
super(widget, self).__init__()
self.setStyleSheet("background: teal;")
widget_label = QLabel("fluid dynamics is cool")
show_pop_up = QPushButton("show pop up")
pop_up = QDialog(self)
pop_up_label = QLabel("click below to, hopefully, get outta here")
get_outta_here = QPushButton("get outta here")
pop_up_layout = QVBoxLayout()
pop_up_layout.addWidget(pop_up_label)
pop_up_layout.addWidget(get_outta_here)
pop_up.setLayout(pop_up_layout)
def show_popup():
pop_up.show()
def get_out():
from main_test import MainWindow
MainWindow.switch_back(self)
pop_up.reject()
get_outta_here.clicked.connect(get_out)
show_pop_up.clicked.connect(show_popup)
widget_layout = QVBoxLayout()
widget_layout.addWidget(widget_label)
widget_layout.addWidget(show_pop_up)
self.setLayout(widget_layout)
I could merge the code together and make it work but I'm trying to keep the directory clean.
There is a lot going on here, but let's break it down.
The main problem seems to be juggling between modules. Eventhough it might seem appealing to import the modules back and forth, it doesn't really work. What you need to look for, is the built-in Signals module that you can utilize.
Another bigger problem is that you are re-assigning some attributes eventhough you really shouldn't. You also should revisit the condition you are using to assign the .setCurrentWidget. Currently the condition reads as if list1 doesn't exist, do this. Else, do the other. Also, switch_widget should be outside of the def __init__(self):.
I rewrote some parts of the code to make it work with signals as an example for you.
mainwindow.py
import sys
import os
import pathlib
from PySide2.QtWidgets import *
from PySide2 import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from widget_test import widget
list1 = ["item1", "item2", "item3"]
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.resize(400, 300)
self.toolbar = QWidget()
self.toolbar.setFixedHeight(30)
self.toolbar.setStyleSheet("background: grey;")
self.button = QPushButton("Click here!")
t_layout = QHBoxLayout()
t_layout.setMargin(0)
t_layout.addWidget(self.button)
self.toolbar.setLayout(t_layout)
self.p1_label = QLabel("Such empty!")
self.p1_label.setStyleSheet("font-size: 30px;")
self.p1_label.setAlignment(Qt.AlignCenter)
self.p2_widget = QWidget()
self.p2_widget.setStyleSheet("background: orange;")
self.p3 = None
self.sw = QStackedWidget()
self.sw.addWidget(self.p1_label)
self.sw.addWidget(self.p2_widget)
if not list1:
self.sw.setCurrentWidget(self.p1_label)
else:
self.sw.setCurrentWidget(self.p2_widget)
self.mw_layout = QVBoxLayout()
self.mw_layout.addWidget(self.toolbar)
self.mw_layout.addWidget(self.sw)
self.setLayout(self.mw_layout)
self.button.clicked.connect(self.switch_widget)
def switch_widget(self):
self.p3 = widget()
self.p3.update_signal.connect(self.switch_back)
self.sw.addWidget(self.p3)
self.sw.setCurrentWidget(self.p3)
def switch_back(self):
self.sw.removeWidget(self.p3)
if list1:
self.sw.setCurrentWidget(self.p1_label)
else:
self.sw.setCurrentWidget(self.p2_widget)
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
widget.py
import sys
import os
import pathlib
import datetime
from PySide2.QtWidgets import *
from PySide2 import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtCore import Signal
class widget(QWidget):
update_signal = Signal()
def __init__(self):
super(widget, self).__init__()
self.setStyleSheet("background: teal;")
widget_label = QLabel("fluid dynamics is cool")
show_pop_up = QPushButton("show pop up")
pop_up = QDialog(self)
pop_up_label = QLabel("click below to, hopefully, get outta here")
get_outta_here = QPushButton("get outta here")
pop_up_layout = QVBoxLayout()
pop_up_layout.addWidget(pop_up_label)
pop_up_layout.addWidget(get_outta_here)
pop_up.setLayout(pop_up_layout)
def show_popup():
pop_up.show()
def get_out():
self.update_signal.emit()
pop_up.reject()
get_outta_here.clicked.connect(get_out)
show_pop_up.clicked.connect(show_popup)
widget_layout = QVBoxLayout()
widget_layout.addWidget(widget_label)
widget_layout.addWidget(show_pop_up)
self.setLayout(widget_layout)
Finally, check Python coding conventions for naming and other "minor" details.

Extracting certain parts of a webpage using PyQt5 and displaying them

I want to make GUI application which asks the user for the champion they want to check and then their role (e.g Middle, Jungle, Top, ADC, Support) and then it will display the "Most Frequent Runes" and some other data on the website. I believe PyQt5 would be the best python GUI for this as it has embedded webpages but please suggest alternatives.
With this code:
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import QApplication
import sys
#champion = input("What champion would you like to check? ")
champions = "Katarina"
#role = input("What role are you playing (Middle, Jungle, Top, ADC, Support)? ")
roles = "Middle"
URL = f"https://champion.gg/champion/{champions.capitalize()}/{roles.capitalize()}?"
app = QApplication(sys.argv)
web = QWebEngineView()
web.load(QUrl(URL))
web.show()
sys.exit(app.exec_())
It displays the whole webpage but I only want the "Most frequent Runes" section shown like it is like this:
and then hold it as a variable (QLabel?) that can then be placed wherever I want it. I have tried to look over how to do this but i couldn't find a solution. I would rather have done it using tkinter but it seems that isn't possible (or as far as I have been able to gather - if their is a way please explain as much as you can how).
I tried scraping the website using bs4 and requests with this code:
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import *
from bs4 import BeautifulSoup
import requests
import time
import sys
#champion = input("What champion would you like to check? ")
champions = "Katarina"
#role = input("What role are you playing (Middle, Jungle, Top, ADC, Support)? ")
roles = "Middle"
URL = f"https://champion.gg/champion/{champions.capitalize()}/{roles.capitalize()}?"
app = QApplication(sys.argv)
page = requests.get('https://champion.gg/champion/Katarina/Middle?')
soup = BeautifulSoup(page.text, 'lxml')
championData = soup.find('div', 'summoner-text')
window = QWidget()
window.setWindowTitle("League of Legends helper")
window.setGeometry(100, 100, 550, 250)
runes = QLabel(championData, parent=window)
but it just produces errors which I haven't fully been able to understand.
Error:
Traceback (most recent call last):
File "(FILEPATH)", line 32, in <module>
runes = QLabel(championData, parent=window)
TypeError: arguments did not match any overloaded call:
QLabel(parent: QWidget = None, flags: Union[Qt.WindowFlags, Qt.WindowType] = Qt.WindowFlags()): argument 1 has unexpected type 'Tag'
QLabel(str, parent: QWidget = None, flags: Union[Qt.WindowFlags, Qt.WindowType] = Qt.WindowFlags()): argument 1 has unexpected type 'Tag'
BeautifulSoup's is an HTML parser so each node of the DOM has a wrapper that allows access to its properties, so championData is not a string causing the error.
Even so, you would extract the HTML from the node, it would be useless because the "requests" library does not obtain the HTML generated dynamically by javascript, in addition, the styles would not be kept as they depend on other files.
A possible solution for this case is to extract the HTML from that node and place it in the same document using javascript:
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
def main(*, champions, roles):
url = f"https://champion.gg/champion/{champions.capitalize()}/{roles.capitalize()}?"
app = QtWidgets.QApplication(sys.argv)
web = QtWebEngineWidgets.QWebEngineView()
web.resize(640, 480)
progress_dialog = QtWidgets.QProgressDialog()
progress_dialog.setLabelText(
"""""<p><span style=" font-size:20pt; font-weight:600;">Loadding ...</span></p>"""
)
progress_dialog.resize(640, 480)
progress_dialog.show()
web.loadProgress.connect(progress_dialog.setValue)
button = progress_dialog.findChild(QtWidgets.QPushButton)
if button is not None:
button.clicked.connect(QtCore.QCoreApplication.quit)
def on_load_finished():
codes = [
"""var iterator = document.evaluate("/html[1]/body[1]/div[1]/div[2]/div[3]/div[2]/div[2]/div[1]/div[1]/div[2]/div[1]/div[3]", document, null, XPathResult.ANY_TYPE, null)""",
"""var e = iterator.iterateNext() """,
"""document.body.innerHTML = e.innerHTML""",
"""document.body.children[0].style.marginTop = "10px" """,
]
for code in codes:
web.page().runJavaScript(code)
web.move(progress_dialog.pos())
web.show()
progress_dialog.close()
web.loadFinished.connect(on_load_finished)
web.load(QtCore.QUrl(url))
sys.exit(app.exec_())
if __name__ == "__main__":
main(champions="Katarina", roles="Middle")
Update:
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self._champion_le = QtWidgets.QLineEdit(placeholderText=self.tr("champion"))
self._role_cb = QtWidgets.QComboBox()
self._web = QtWebEngineWidgets.QWebEngineView()
self._search_btn = QtWidgets.QPushButton(self.tr("Search"))
self._stacked = QtWidgets.QStackedWidget()
self._progress_bar = QtWidgets.QProgressBar()
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QGridLayout(central_widget)
lay.addWidget(self._champion_le, 0, 0)
lay.addWidget(self._role_cb, 0, 1)
lay.addWidget(self._search_btn, 0, 2)
lay.addWidget(self._stacked, 1, 0, 1, 3)
container = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(container)
lay.addWidget(
QtWidgets.QLabel(
self.tr(
"""<p><span style="font-size:20pt; font-weight:600;">Loadding ...</span></p>"""
)
)
)
lay.addWidget(self._progress_bar)
self._stacked.addWidget(QtWidgets.QWidget())
self._stacked.addWidget(container)
self._stacked.addWidget(self._web)
self._role_cb.addItems(["Top", "Jungle", "Middle", "ADC", "Support"])
self._search_btn.clicked.connect(self.on_clicked)
self._web.loadFinished.connect(self.on_load_finished)
self._web.loadProgress.connect(self._progress_bar.setValue)
self.resize(640, 480)
self._champion_le.setText("Aatrox")
self._role_cb.setCurrentText("Top")
#QtCore.pyqtSlot()
def on_clicked(self):
champion = self._champion_le.text()
role = self._role_cb.currentText()
if champion:
self._stacked.setCurrentIndex(1)
self.change(champion, role)
def change(self, champion, role):
url = f"https://champion.gg/champion/{champion.capitalize()}/{role}?"
self._web.load(QtCore.QUrl(url))
#QtCore.pyqtSlot(bool)
def on_load_finished(self, ok):
if ok:
codes = [
"""var iterator = document.evaluate("/html[1]/body[1]/div[1]/div[2]/div[3]/div[2]/div[2]/div[1]/div[1]/div[2]/div[1]/div[3]", document, null, XPathResult.ANY_TYPE, null)""",
"""var e = iterator.iterateNext() """,
"""document.body.innerHTML = e.innerHTML""",
"""document.body.children[0].style.marginTop = "10px" """,
]
for code in codes:
self._web.page().runJavaScript(code)
self._stacked.setCurrentIndex(2)
def main():
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Capture Screen with PyQt4 or PySide, except specific widget?

I'm trying to capture the screen area in the region of my pyqt4 app translucent, but i want exclude the widget "betwn = QPushButton('test')" in the capture, I'm trying to hide the widget using hide() like this: betwn.hide(), for be excluded before the capture, but not works, the "betwn" even hidden anyway is will captured.
Here my PyQt4 Code:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from datetime import datetime
app = QApplication(sys.argv)
widget = QWidget()
widget.setLayout(QVBoxLayout())
widget.setAttribute(Qt.WA_TranslucentBackground)
label = QLabel()
widget.layout().addWidget(label)
def capture():
p = QPixmap.grabWindow(QApplication.desktop().winId(),widget.geometry().x(),widget.geometry().y(),widget.geometry().width(),widget.geometry().height())
label.setPixmap(p)
def shoot():
betwn.hide()
capture()
betwn.show()
button = QPushButton('take screenshot', clicked=shoot)
betwn = QPushButton('test')
widget.layout().addWidget(button)
widget.layout().addWidget(betwn)
widget.show()
app.exec_()
Here my PySide Code:
import sys
from PySide.QtGui import *
from PySide.QtCore import *
from datetime import datetime
app = QApplication(sys.argv)
widget = QWidget()
widget.setLayout(QVBoxLayout())
widget.setAttribute(Qt.WA_TranslucentBackground)
label = QLabel()
widget.layout().addWidget(label)
def capture():
p = QPixmap.grabWindow(QApplication.desktop().winId(),widget.geometry().x(),widget.geometry().y(),widget.geometry().width(),widget.geometry().height())
label.setPixmap(p)
def shoot():
betwn.hide()
capture()
betwn.show()
button = QPushButton('take screenshot', clicked=shoot)
betwn = QPushButton('test')
widget.layout().addWidget(button)
widget.layout().addWidget(betwn)
widget.show()
app.exec_()
How i can do for exclude the widget "betwn = QPushButton('test')" in the capture? or If you know other way to capture the desktop area using the of the window without capture the window, using the coordinates of the window and the width and height?
Like this:
QPixmap.grabWindow(QApplication.desktop().winId(),widget.geometry().x(),widget.geometry().y(),widget.geometry().width(),widget.geometry().height());
When you call the hide method, it does not mean that the button will be closed at that moment, since it involves a repainting process that ends after the synchronous task ends, in these cases you must give adequate time for Qt to do that work and that can be done. make a QTimer::singleShot().
app = QApplication(sys.argv)
widget = QWidget()
widget.setLayout(QVBoxLayout())
widget.setAttribute(Qt.WA_TranslucentBackground)
label = QLabel()
widget.layout().addWidget(label)
def capture():
p = QPixmap.grabWindow(
QApplication.desktop().winId(),
*widget.geometry().getRect()
)
label.setPixmap(p)
betwn.show()
def shoot():
betwn.hide()
QTimer.singleShot(1, capture)
button = QPushButton("take screenshot", clicked=shoot)
betwn = QPushButton("test")
widget.layout().addWidget(button)
widget.layout().addWidget(betwn)
widget.show()
sys.exit(app.exec_())

Categories