I have a list of QLabel and want to learn which QLabel clicked . When i look for the making QLabel clickable , this code has worked :
labels[i].mousePressEvent = self.print_some
def print_some(self, event):
print("Clicked")
But I didn't figure out which object clicked . How can i do that ?
You can easily make custom receivers for events, which would contain the event source information:
import functools
labels[i].mousePressEvent = functools.partial(self.print_some, source_object=labels[i])
def print_some(self, event, source_object=None):
print("Clicked, from", source_object)
Related
How do you simulate mouse hover for PyQt5 to a coordinate? Perhaps with QPoint.
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import Qt, QUrl, QTimer
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
class Screenshot(QWebEngineView):
def capture(self, url, output_file):
self.output_file = output_file
self.load(QUrl(url))
self.loadFinished.connect(self.on_loaded)
# Create hidden view without scrollbars
#self.setAttribute(Qt.WA_DontShowOnScreen)
self.page().settings().setAttribute(
QWebEngineSettings.ShowScrollBars, False)
self.show()
def on_loaded(self):
size = self.page().contentsSize().toSize()
self.resize(size)
# Wait for resize
print("Capturing")
QTimer.singleShot(3000, self.take_screenshot)
def take_screenshot(self):
self.grab().save(self.output_file, b'PNG')
self.app.quit()
app = QApplication(sys.argv)
screenshots = {}
screenshot = Screenshot()
screenshot.app = app
screenshot.capture('https://zoom.earth/maps/wind-speed/#view=13.955336,121.109689,11z', 'wind.png')
Such that it shows a UI overlay like in the image.
Zoom Wind map, Mouse hovered at center
Faking a mouse event is not that difficult, it's just a matter of creating a QMouseEvent with the correct arguments:
event = QMouseEvent(QEvent.MouseMove,
QPoint(someX, someY),
Qt.NoButton,
Qt.MouseButtons(Qt.NoButton),
Qt.KeyboardModifiers(Qt.NoModifier))
the QPoint argument represents the point in which the cursor is supposed to be, in local coordinates: in the following example I'll use self.rect().center(), which is the exact center in the rectangle of the viewport;
the next argument is the mouse button that generates the QMouseEvent; since a mouse move event is not generated by a mouse button press, it should always be NoButton;
. the argument after represents the buttons that are pressed at the time of the event; since we suppose that this is just a "hover" movement, we still have a NoButton value (but using the MouseButton flag, since it represents a flag and multiple buttons could be pressed);
the last is obviously about the keyboard modifiers, and we again don't need any of that, but still we must use a flag;
The important part is to send the event to the correct widget. QWebEngineView uses a private QWidget subclass to show the actual content and receive user interaction, so we need to find that widget.
def on_loaded(self):
size = self.page().contentsSize().toSize()
self.resize(size)
# Get the actual web content widget
child = self.findChild(QWidget)
# Create a fake mouse move event
event = QMouseEvent(QEvent.MouseMove,
self.rect().center(),
Qt.NoButton, Qt.MouseButtons(Qt.NoButton),
Qt.KeyboardModifiers(Qt.NoModifier))
# Send the event
QApplication.postEvent(child, event)
# Wait for resize
print("Capturing")
QTimer.singleShot(3000, self.take_screenshot)
OS: W10. This may be significant. If you have different results on a different platform, feedback would be helpful.
Here is an MRE. If you run it and go Ctrl+O, the menu labels become greyed. If you select a file in the QFileDialog by clicking the "Open" button or using its mnemonic (Alt+O), the open-file dialog is dismissed and the "Files" and "Help" menus become un-greyed.
However, if you go Ctrl+O again, and this time enter the name of a file in the "File name" box (QLineEdit), and then press Return, the dialog is dismissed (with a successful selection result) but the "Files" and "Help" menus remain greyed-out. It looks like this:
import sys, os
from PyQt5 import QtWidgets, QtCore, QtGui
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Greying of menus MRE')
self.setGeometry(QtCore.QRect(100, 100, 400, 200))
menubar = QtWidgets.QMenuBar(self)
self.setMenuBar(menubar)
self.files_menu = QtWidgets.QMenu('&Files', self)
menubar.addMenu(self.files_menu)
self.help_menu = QtWidgets.QMenu('&Help', self)
menubar.addMenu(self.help_menu)
self.new_action = QtWidgets.QAction('&New', self)
self.files_menu.addAction(self.new_action)
self.open_action = QtWidgets.QAction('&Open', self)
self.files_menu.addAction(self.open_action)
self.open_action.setShortcut("Ctrl+O")
self.open_action.triggered.connect(self.open_file)
def focusInEvent(self, event ):
print('main_window focusInEvent')
super().focusInEvent(event)
def focusOutEvent(self, event ):
print('main_window focusOutEvent')
super().focusInEvent(event)
def activateWindow(self):
print('main_window activateWindow')
super().activateWindow()
def open_file(self):
print('open file')
main_window_self = self
# open_doc_dialog = QtWidgets.QFileDialog(self.get_main_window())
class OpenDocFileDialog(QtWidgets.QFileDialog):
def accepted(self):
print('accepted')
super().accepted()
def accept(self):
print('accept')
super().accept()
def close(self):
print('close')
super().close()
def done(self, r):
print(f'done r {r}')
# neither of these solves the problem:
# main_window_self.activateWindow()
# main_window_self.files_menu.activateWindow()
super().done(r)
def hide(self):
print(f'hide')
super().hide()
def focusInEvent(self, event ):
print('focusInEvent')
super().focusInEvent(event)
def focusOutEvent(self, event ):
print('focusOutEvent')
super().focusInEvent(event)
def activateWindow(self):
print('activateWindow')
super().activateWindow()
open_doc_dialog = OpenDocFileDialog(self)
open_doc_dialog.setWindowTitle('Choose file')
open_doc_dialog.setDirectory(os.getcwd())
# we cannot use the native dialog, because we need control over the UI
options = open_doc_dialog.Options(open_doc_dialog.DontUseNativeDialog)
open_doc_dialog.setOptions(options)
open_doc_button = open_doc_dialog.findChild(QtWidgets.QDialogButtonBox).button(QtWidgets.QDialogButtonBox.Open)
lineEdit = open_doc_dialog.findChild(QtWidgets.QLineEdit)
# this does not solve the problem
# lineEdit.returnPressed.disconnect()
# lineEdit.returnPressed.connect(open_doc_button.click)
print(f'open_doc_button {open_doc_button}, lineEdit {lineEdit}')
# show the dialog
dialog_code = open_doc_dialog.exec()
if dialog_code != QtWidgets.QDialog.Accepted: return
sel_files = open_doc_dialog.selectedFiles()
print(f'sel_files: {sel_files}')
app = QtWidgets.QApplication([])
main_window = MainWindow()
main_window.show()
sys.exit(app.exec())
This problem can be understood, if not solved, with reference to this answer.
Note that this greying-out is not disablement. As explained in the above link, this has to do with "active/inactive states" of the menus (or their labels). The menus remain enabled throughout, although in this case it's impossible to know that while the open-file dialog is showing because it is modal. Clicking on one menu after the dialog has gone, or just hovering over it, is enough to un-grey them both...
The explanation, as I understand it, is that the "File name" box QLineEdit has a signal, returnPressed, which appears to activate something subtley different to the slot which is invoked when you use the "Choose" button. You can see I have experimented with trying to re-wire that signal, to no avail.
The method done of the QFileDialog appears to be called however the dialog closes (unlike close!), so I tried "activating" the main window... and then the individual QMenus... Doesn't work.
I am not clear how to get a handle on this "active state" business or why the slot connected to returnPressed is (seemingly) unable to give the "active state" back to the menus when the other slot manages to do so.
Edit
Searching on Musicamante's "unpolishing" suggestion led me to this:
lineEdit.returnPressed.disconnect()
def return_pressed():
style = main_window_self.menubar.style()
style.unpolish(main_window_self.menubar)
open_doc_button.click()
lineEdit.returnPressed.connect(return_pressed)
... unfortunately this doesn't work.
This looks like a possible Windows-related bug, since I can't reproduce it on Linux. As a work-around, you could try forcing a repaint after the dialog closes:
# show the dialog
dialog_code = open_doc_dialog.exec()
self.menubar.repaint()
Finally got it, thanks to Musicamante's suggestion:
lineEdit.returnPressed.disconnect()
def return_pressed():
style = main_window_self.menubar.style()
style.unpolish(main_window_self.menubar)
open_doc_button.click()
main_window_self.menubar.repaint()
lineEdit.returnPressed.connect(return_pressed)
... I actually tried this several times, just to make sure it was doing what was intended. So in fact, fortunately, no single-shot timer was needed in this case.
I have been trying to create GUI program for my laboratory colleagues.
I have some textboxes on my main window to show files directory that added by user.
I am new in PyQt5 and I want to add feature to my textboxes.
For example, textbox=QLineEdit().. textbox1=.. textbox2=..
So I want to choose textbox before I add file by clicking on the main window then directory of file will be written correct textbox.
I tried to make custom clickablelineedit but I did not succeed.
Is there another way to do it ?
King regards,
EDIT:
class Mutation_Finder():
def __init__(self):
... (Main Window Code)
def openFileNamesDialog(self, **kwargs):
self.options = QFileDialog.Options()
self.options |= QFileDialog.DontUseNativeDialog
self.files, self._= QFileDialog.getOpenFileNames(self,"Dosya Ac","","All Files (*);;.abi,.fasta (*.abi,*fasta)", options=self.options)
def toDoSomething():
if textbox is clicked:
for i in range(len(self.files):
self.textbox.insert(self.files[i])
if textbox1 is clicked:
...
if textbox2 is clicked:
...
see the main window image
SOLVED:
class cQLineEdit(QLineEdit):
clicked=pyqtSignal()
def __init__(self,*args, **kwargs):
super().__init__(*args,**kwargs)
def mousePressEvent(self,QMouseEvent):
self.clicked.emit()
class MainClass(cQLineEdit)
textbox=cQLineEdit(self)
....
....
self.clicked.connect(...)
I solved it with this method but I have still problem with clicked event because when I click out of the QLineEdit I have Error:
self.clicked.emit() AttributeError: 'className' does not have a
signal with the signature clicked()
like this and I don't have any idea how to deal with as well.
Apart from that, here is link that related with solution.
Pyqt 5 how to make QLineEdit clickable
I have a app that uses PyQt4 for GUI. But having some issues with connecting to signals.
I made a button like this
self.button=QtGui.QPushButton("Load File")
QObject.connect( self.button, SIGNAL('clicked ()'), self.clicked )
And it perfectly fires the following function:
def clicked(self):
So in the same manner i made a input element. However the input element signal does not fire when i change the text.
self.filter=QtGui.QInputDialog() #Create the Input Dialog
self.filter.setInputMode (self.filter.InputMode.TextInput ) #Change the input type to text
self.filter.setOption(self.filter.InputDialogOption.NoButtons,True) #I don't need the buttons so i have removed them
self.filter.setLabelText("Filter") #I change the label to "filter"
self.connect( self.filter, QtCore.SIGNAL("textValueChanged()"), self.filterUpdate ) #I connect to the signal textValueChanged() that should be fired when the text is changed and make it fire the filterUpdate() function
The following is never fired:
def filterUpdate(self):
print "Hello"
This works here:
from PyQt4 import QtCore, QtGui
import sys
app = QtGui.QApplication(sys.argv)
def filterUpdate():
print('!')
filter = QtGui.QInputDialog()
filter.setInputMode (filter.TextInput)
filter.setOption(filter.NoButtons, True)
filter.setLabelText("Filter")
filter.textValueChanged.connect(filterUpdate)
filter.show()
sys.exit(app.exec_())
I have a layout with 5 buttons which I act as "menus", so you click on one button and one view will show up, you click another button and another view shows up. I need to find out which button is clicked so I can do something based on which button is pressed. Something like
if button1_is_clicked:
do_something()
else:
do_something_else()
What would be the best way to approach this?
Here is my code:
I want to be able to change the stylesheet of the button, so an active state and a non-active state
from PySide import QtCore
from PySide import QtGui
import VulcanGui
#--------------------------------------------------------------------------
class Program(QtGui.QMainWindow, VulcanGui.Ui_MainWindow):
def __init__(self, parent=None):
""" Initialize and setup the User Interface """
super(Program, self).__init__(parent)
self.setupUi(self)
""" Populate the Main Area """
self.mainArea.setHtml(self.intro_text())
""" Button Signal/Slots """
self.introButton.toggled.connect(self.intro_area)
self.runVulcanButton.clicked.connect(self.vulcan_run_area)
self.vulcanLogButton.clicked.connect(self.vulcan_log_area)
self.hostFileButton.clicked.connect(self.edit_host_area)
self.configEditButton.clicked.connect(self.edit_config_area)
def intro_text(self):
content_file = open("../content/intro_text.html").read()
return content_file
'''
Get the content to print
'''
def intro_area(self):
content_file = open("../content/intro_text.html").read()
self.mainArea.setHtml(content_file)
'''
Function that will display the data when the 'Run Vulcan' button is pressed
'''
def vulcan_run_area(self):
self.mainArea.setPlainText("Button Two ")
'''
Function that will display the data when the 'Vulcan Log' button is pressed
'''
def vulcan_log_area(self):
self.mainArea.setPlainText("Button Three")
'''
Function that will display the data when the 'Edit Host File' button is pressed
'''
def edit_host_area(self):
self.mainArea.setPlainText("Button Four")
'''
Function that will display the data when the 'Edit Config File' button is pressed
'''
def edit_config_area(self):
self.mainArea.setPlainText("Button Five")
#--------------------------------------------------------------------------
if __name__ == "__main__":
import sys
program = QtGui.QApplication(sys.argv)
mWindow = Program()
mWindow.show()
sys.exit(program.exec_())
I suggest you learn the basics of Qt to get acquainted with signals and slots.
You need to make the initially visible QPushButtons checkable (otherwise the 'revealed' buttons will only appear whilst the button is held down), and connect the toggled(bool) signal to the setVisible(bool) slot of the buttons you want to 'reveal'. Obviously for the buttons that are initially invisible, you would have to call setVisible(false) upon instantiation.
There are other, more reusable, ways of achieving the same effect - but this will get you started.