In main.py
returnCode = self.rouDialogForm.exec_()
if returnCode == QtWidgets.QDialog.Accepted:
print(float(self.rouDialogForm.ui.leStartMhz.text()))
if returnCode ==QtWidgets.QDialog.Rejected:
print(float(self.rouDialogForm.ui.leStopMhz.text()))
In rouDialog.py
def setupUi(self, Dialog):
#GUI CODE
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.butConnect.clicked.connect(self.acceptDialog)
def acceptDialog(self):
self.accept()
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
#Label set texts are here
import myResources_rc
I can catch the Rejected signal that is generated after clicking the window closing icon and print out the required text from the line edit.
But when I press the button that will generate accept signal(but connect) program just crashes run time.
I tried different syntax and different imports to make it work.
attempt #1: in rouDialog.py instead of self.accept()
self.done(QtWidgets.QDialog.Accepted)
another attempt: in rouDialog.py instead of self.accept()
super(Ui_Dialog,self).accept()
another one:
QtWidgets.QDialog.accept(self)
SOLVED:
Adding this to my rouDialog.py solved all my problems.Hope it will help someone else in future.
self.butReadout.clicked.connect(Dialog.accept)
#QtCore.pyqtSlot()
def accept(self):
pass
Edit: I can't mark my answer as correct , since i need to wait 2 days.
Related
I have a custom QWidget that I have embedded into a QTableWidget.
When I toggle the QCheckBoxes and modify the text in the QLineEdit widgets, the program is not able to distinguish the widgets in rows 2 and 1 from the widgets in row 0. How can I change the program so that it prints the correct row and column of the QLineEdit widget that is being edited or the Checkbox that is being toggled?
Figure 1 shows a screenshot of the program with the output after selecting the third checkbox many times in Visual Studio Code. The output is expected to read “2 0” repeatedly but instead it reads “0 0”.
Figure 2 Similarly, when I modify the text in the QLineEdit in cell 2,0 from “My Custom Text” to “Text” the program prints “Handle Cell Edited 0,0”, although it is expected to print “Handle Cell Edited 2,0 Cell 2,0 was changed to Text”.
Code:
# Much of this code is copy pasted form user: three_pineapples post on stackoverflow:
# https://stackoverflow.com/a/26311179/18914416
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QTableWidget, \
QApplication, QTableWidgetItem, QLineEdit, QCheckBox
from PyQt5 import QtGui
class SimpleTable(QTableWidget):
def __init__(self,window):
# Call the parent constructor
QTableWidget.__init__(self)
self.window = window
class myWidget(QWidget):
#This code is adapted paritally form a post by user sebastian at:
#https://stackoverflow.com/a/29764770/18914416
def __init__(self,parent=None):
super(myWidget,self).__init__()
self.Layout1 = QHBoxLayout()
self.item = QLineEdit("My custom text")
#https://stackabuse.com/working-with-pythons-pyqt-framework/
self.Checkbox = QCheckBox()
self.Checkbox.setCheckState(Qt.CheckState.Unchecked)
self.Layout1.addWidget(self.Checkbox)
self.Layout1.addWidget(self.item)
#https://stackoverflow.com/questions/29764395/adding-multiple-widgets-to-qtablewidget-cell-in-pyqt
self.item.home(True)
#https://www.qtcentre.org/threads/58387-Left-text-alignment-for-long-text-on-QLineEdit
self.setLayout(self.Layout1)
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
layout = QHBoxLayout()
self.setLayout(layout)
self.table_widget = SimpleTable(window=self)
layout.addWidget(self.table_widget)
self.table_widget.setColumnCount(3)
self.table_widget.setHorizontalHeaderLabels(['Colour', 'Model'])
items = [('Red', 'Toyota'), ('Blue', 'RV'), ('Green', 'Beetle')]
for i in range(len(items)):
c = QTableWidgetItem(items[i][0])
m = QTableWidgetItem(items[i][1])
self.table_widget.insertRow(self.table_widget.rowCount())
self.table_widget.setItem(i, 1, c)
self.table_widget.setItem(i, 2, m)
myWidget1 = myWidget()
myWidget1.Checkbox.stateChanged.connect(self.handleButtonClicked)
myWidget1.item.editingFinished.connect(self.handle_cell_edited)
self.table_widget.setCellWidget(i,0,myWidget1)
myWidget1.Layout1.setContentsMargins(50*i+10,0,0,0)
self.show()
self.table_widget.itemChanged.connect(self.handle_cell_edited)
def handleButtonClicked(self):
#Adapted from a post by user: Andy at:
# https://stackoverflow.com/a/24149478/18914416
button = QApplication.focusWidget()
# or button = self.sender()
index = self.table_widget.indexAt(button.pos())
if index.isValid():
print(index.row(), index.column())
# I added this fuction:
def handle_cell_edited(self):
if QApplication.focusWidget() != None:
index = self.table_widget.indexAt(QApplication.focusWidget().pos())
x,y = index.column(),index.row()
if index.isValid():
print("Handle Cell Edited",index.row(), index.column())
if self.table_widget.item(y,x)!= None:
print(f"Cell {x},{y} was changed to {self.table_widget.item(y,x).text()}.")
def main():
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
main()
What I've Tried So Far:
I learned that QT has two types of widgets that can be embedded in a table; a QTableWigetItem which can be inserted into a table using setItem()(3) and Qwidgets, which can be placed into a table using setCellWidget().(4) Generally, I know that using a QTableWigetItem one can set the item.setFlags(Qt.ItemFlag.ItemIsUserCheckable)
flag to create a checkbox in the cell. (3) However, when using the QTableWigetItem, I wasn’t able to find a way to indent the checkboxes. Because giving each checkbox its own indentation level is important in the context of my program, I’ve decided to use Qwidgets instead of QTableWigetItems in the few select cells where indenting is important.
I’ve read that by creating a QItemDelegate(5)(6), you can do a lot more with setting QWidgets in boxes. However, creating a delegate seems complicated, so I’d prefer to avoid this if possible. If there is no other way to make the program register the correct cell number of the cell being edited, creating a delegate will be the next thing I look into.
For anyone who might want to experiment with QTableWigetItems in this application, here is an equivalent program that uses QTableWigetItems instead of QWidgets but doesn't permit separate indentation or editing of the text field in column 0. For either and both of these two reasons, a QTableWigetItem seems not to be usable for the checkboxes in column 0.
Less Successful Attempt using QTableWidgetItem:
#Much of this code is copy pasted form user: three_pineapples post on stackoverflow:
# https://stackoverflow.com/a/26311179/18914416
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QTableWidget, \
QApplication, QTableWidgetItem, QLineEdit, QCheckBox
from PyQt5 import QtGui
class SimpleTable(QTableWidget):
def __init__(self,window):
QTableWidget.__init__(self)
self.window = window
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
layout = QHBoxLayout()
self.setLayout(layout)
self.table_widget = SimpleTable(window=self)
layout.addWidget(self.table_widget)
self.table_widget.setColumnCount(3)
self.table_widget.setHorizontalHeaderLabels(['Colour', 'Model'])
items = [('Red', 'Toyota'), ('Blue', 'RV'), ('Green', 'Beetle')]
for i in range(len(items)):
c = QTableWidgetItem(items[i][0])
m = QTableWidgetItem(items[i][1])
self.table_widget.insertRow(self.table_widget.rowCount())
self.table_widget.setItem(i, 1, c)
self.table_widget.setItem(i, 2, m)
item = QTableWidgetItem("My Custom Text")
item.setFlags(Qt.ItemFlag.ItemIsUserCheckable| Qt.ItemFlag.ItemIsEnabled)
item.setCheckState(Qt.CheckState.Unchecked)
self.table_widget.setItem(i,0,item)
#https://youtu.be/DM8Ryoot7MI?t=251
self.show()
#I added this line:
self.table_widget.itemChanged.connect(self.handle_cell_edited)
def handleButtonClicked(self):
#Adapted from a post by user: Andy at:
# https://stackoverflow.com/a/24149478/18914416
button = QApplication.focusWidget()
# or button = self.sender()
index = self.table_widget.indexAt(button.pos())
if index.isValid():
print(index.row(), index.column())
# I added this fuction:
def handle_cell_edited(self):
if QApplication.focusWidget() != None:
index = self.table_widget.indexAt(QApplication.focusWidget().pos())
x,y = index.column(),index.row()
if index.isValid():
print("Handle Cell Edited",index.row(), index.column())
if self.table_widget.item(y,x)!= None:
print(f"Cell {x},{y} was changed to {self.table_widget.item(y,x).text()}.")
def main():
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
main()
Bibliography:
1.https://i.stack.imgur.com/FudE3.png
2.https://i.stack.imgur.com/C2ypp.png
3.https://youtu.be/DM8Ryoot7MI?t=251
4.https://stackoverflow.com/questions/24148968/how-to-add-multiple-qpushbuttons-to-a-qtableview/24149478#24149478
5.Creating a QItemDelegate for QWidgets, https://stackoverflow.com/a/35418141/18914416
6.Need to create a QItemDelegate to add a stylesheet to QTableWidgetItems: https://forum.qt.io/topic/13124/solved-qtablewidgetitem-set-stylesheet
The geometry of a widget is always relative to its parent.
In your first example, the problem is that the pos() returned for the widget is relative to the myWidget container, and since the vertical position is always a few pixels below the top of the parent (the layout margin), you always get the same value.
The second example has another conceptual problem: the checkbox of a checkable item is not an actual widget, so the widget you get is the table itself.
def handle_cell_edited(self):
# this will print True
print(isinstance(QApplication.focusWidget(), QTableWidget))
As explained above, the geometry is always relative to the parent, so you will actually get the position of the table relative to the window.
The solution to the first case is quite simple, as soon as you understand the relativity of coordinate systems. Note that you shall not rely on the focusWidget() (the widget might not accept focus), but actually get the sender(), which is the object that emitted the signal:
def handleButtonClicked(self):
sender = self.sender()
if not self.table_widget.isAncestorOf(sender):
return
# the widget coordinates must *always* be mapped to the viewport
# of the table, as the headers add margins
pos = sender.mapTo(self.table_widget.viewport(), QPoint())
index = self.table_widget.indexAt(pos)
if index.isValid():
print(index.row(), index.column())
In reality, this might not be that necessary, as an item delegate will suffice if the indentation is the only requirement: the solution is to properly set the option.rect() within initStyleOption() and use a custom role for the indentation:
IndentRole = Qt.UserRole + 1
class IndentDelegate(QStyledItemDelegate):
def initStyleOption(self, opt, index):
super().initStyleOption(opt, index)
indent = index.data(IndentRole)
if indent is not None:
left = min(opt.rect.right(),
opt.rect.x() + indent)
opt.rect.setLeft(left)
class SimpleTable(QTableWidget):
def __init__(self,window):
QTableWidget.__init__(self)
self.window = window
self.setItemDelegateForColumn(0, IndentDelegate(self))
class Window(QWidget):
def __init__(self):
# ...
for i in range(len(items)):
# ...
item.setData(IndentRole, 20 * i)
I revised the whole question because the behavior I want is hard to implement and actually use.
I'm trying to imitate the behavior in the File Explorer where when I press Shift while dragging, the file will be moved instead of copied.
This is the behavior I'm trying to imitate:
The behavior: is I'm using my LeftClick for selecting, and dragging.
About The behavior itself:
I overridden the mousePressEvent and mouseMoveEvent to start the drag. When the drag is created, it uses QTimer to detect if I pressed the Control and Shift modifier. Once a modifier is detected it sets the default drop action using setDefaultDropAction. (I think I should use setDropAction but It's only available in the dragMoveEvent and I'm doing it inside the QDrag Class)
The Issues:
Part of the behavior is working now but there is still some issues.
Even I press Shift, the DropIndicator is not changing from + to ->
Related to the issue above, The dropAction is only copyAction instead of moveAction even I'm pressing the Shift key.
My Question: What causes these issues? My gut tells me that I should've used setDropAction instead of setDefaultDropAction but again it's only available in the dragMoveEvent
My Testing Code:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class ModifiedQDrag(QDrag):
def __init__(self, source):
super().__init__(source)
self.timer = QTimer(self)
self.timer.timeout.connect(self.process_event)
self.timer.setInterval(100)
self.timer.start()
def process_event(self):
if qApp.keyboardModifiers() & Qt.ControlModifier:
self.source().setDefaultDropAction(Qt.CopyAction)
elif qApp.keyboardModifiers() & Qt.ShiftModifier:
print("shift pressed")
self.source().setDefaultDropAction(Qt.MoveAction)
class Tree(QTreeView):
def __init__(self):
super().__init__()
self.setDragDropMode(QAbstractItemView.DragDrop)
self.setDropIndicatorShown(True)
self.viewport().setAcceptDrops(True)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# -- mouse dragging -- #
def mousePressEvent(self, event):
if event.button() == Qt.RightButton:
self.dragStartPosition = event.pos()
return super().mousePressEvent(event)
def mouseMoveEvent(self, event):
if event.buttons() != Qt.RightButton:
return
if ((event.pos() - self.dragStartPosition).manhattanLength() < QApplication.startDragDistance()):
return
drag = ModifiedQDrag(self)
mimeData = QMimeData()
mimeData = self.model().mimeData([self.indexAt(event.pos())])
drag.setMimeData(mimeData)
dragAction = drag.exec(Qt.MoveAction | Qt.CopyAction, Qt.CopyAction)
return super().mouseMoveEvent(event)
def dragMoveEvent(self, event):
m = event.mimeData()
if m.hasUrls():
event.accept()
return
event.ignore()
def dropEvent(self, event):
print("[drop event] - dropped")
class FileSystemView(QWidget):
def __init__(self):
super().__init__()
# -- left side -- #
left_side_dir = r"<Dir>"
self.model = QFileSystemModel()
self.model.setRootPath(left_side_dir)
self.tree = Tree()
self.tree.setModel(self.model)
self.tree.setRootIndex(self.model.index(left_side_dir))
# -- right side -- #
right_side_dir = r"<Dir>"
self.model2 = QFileSystemModel()
self.model2.setRootPath(right_side_dir)
self.tree2 = Tree()
self.tree2.setModel(self.model2)
self.tree2.setRootIndex(self.model2.index(right_side_dir))
# -- layout -- #
self.tree_layout = QHBoxLayout()
self.tree_layout.addWidget(self.tree)
self.tree_layout.addWidget(self.tree2)
self.setLayout(self.tree_layout)
app = QApplication(sys.argv)
demo = FileSystemView()
demo.show()
sys.exit(app.exec_())
Qt can only react to mouse movements in order to trigger changes in the drop action: as the name suggests, dragMoveEvent() can only be called by a mouse move.
Considering that, a possible solution is to manually force the mouse movement whenever the keyboard modifiers change. In this way you don't even need to create a QDrag subclass and you can keep the default behavior.
Be aware that to properly get modifiers, you should not use keyboardModifiers(), but queryKeyboardModifiers(), as the first is only reliable when keyboard events are directly handled and might not be updated with the actual current state of the keyboard.
class Tree(QTreeView):
# ...
def checkDrag(self):
modifiers = qApp.queryKeyboardModifiers()
if self.modifiers != modifiers:
self.modifiers = modifiers
pos = QCursor.pos()
# slightly move the mouse to trigger dragMoveEvent
QCursor.setPos(pos + QPoint(1, 1))
# restore the previous position
QCursor.setPos(pos)
def mouseMoveEvent(self, event):
if event.buttons() != Qt.RightButton:
return
if ((event.pos() - self.dragStartPosition).manhattanLength() < QApplication.startDragDistance()):
return
self.modifiers = qApp.queryKeyboardModifiers()
# a local timer, it will be deleted when the function returns
dragTimer = QTimer(interval=100, timeout=self.checkDrag)
dragTimer.start()
self.startDrag(Qt.MoveAction|Qt.CopyAction)
def dragMoveEvent(self, event):
if not event.mimeData().hasUrls():
event.ignore()
return
if qApp.queryKeyboardModifiers() & Qt.ShiftModifier:
event.setDropAction(Qt.MoveAction)
else:
event.setDropAction(Qt.CopyAction)
event.accept()
I am currently following this tutorial on threading in PyQt (code from here). As it was written in PyQt4 (and Python2), I adapted the code to work with PyQt5 and Python3.
Here is the gui file (newdesign.py):
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'threading_design.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(526, 373)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.subreddits_input_layout = QtWidgets.QHBoxLayout()
self.subreddits_input_layout.setObjectName("subreddits_input_layout")
self.label_subreddits = QtWidgets.QLabel(self.centralwidget)
self.label_subreddits.setObjectName("label_subreddits")
self.subreddits_input_layout.addWidget(self.label_subreddits)
self.edit_subreddits = QtWidgets.QLineEdit(self.centralwidget)
self.edit_subreddits.setObjectName("edit_subreddits")
self.subreddits_input_layout.addWidget(self.edit_subreddits)
self.verticalLayout.addLayout(self.subreddits_input_layout)
self.label_submissions_list = QtWidgets.QLabel(self.centralwidget)
self.label_submissions_list.setObjectName("label_submissions_list")
self.verticalLayout.addWidget(self.label_submissions_list)
self.list_submissions = QtWidgets.QListWidget(self.centralwidget)
self.list_submissions.setBatchSize(1)
self.list_submissions.setObjectName("list_submissions")
self.verticalLayout.addWidget(self.list_submissions)
self.progress_bar = QtWidgets.QProgressBar(self.centralwidget)
self.progress_bar.setProperty("value", 0)
self.progress_bar.setObjectName("progress_bar")
self.verticalLayout.addWidget(self.progress_bar)
self.buttons_layout = QtWidgets.QHBoxLayout()
self.buttons_layout.setObjectName("buttons_layout")
self.btn_stop = QtWidgets.QPushButton(self.centralwidget)
self.btn_stop.setEnabled(False)
self.btn_stop.setObjectName("btn_stop")
self.buttons_layout.addWidget(self.btn_stop)
self.btn_start = QtWidgets.QPushButton(self.centralwidget)
self.btn_start.setObjectName("btn_start")
self.buttons_layout.addWidget(self.btn_start)
self.verticalLayout.addLayout(self.buttons_layout)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Threading Tutorial - nikolak.com "))
self.label_subreddits.setText(_translate("MainWindow", "Subreddits:"))
self.edit_subreddits.setPlaceholderText(_translate("MainWindow", "python,programming,linux,etc (comma separated)"))
self.label_submissions_list.setText(_translate("MainWindow", "Submissions:"))
self.btn_stop.setText(_translate("MainWindow", "Stop"))
self.btn_start.setText(_translate("MainWindow", "Start"))
and the main script (main.py):
from PyQt5 import QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal, QObject
import sys
import newdesign
import urllib.request
import json
import time
class getPostsThread(QThread):
def __init__(self, subreddits):
"""
Make a new thread instance with the specified
subreddits as the first argument. The subreddits argument
will be stored in an instance variable called subreddits
which then can be accessed by all other class instance functions
:param subreddits: A list of subreddit names
:type subreddits: list
"""
QThread.__init__(self)
self.subreddits = subreddits
def __del__(self):
self.wait()
def _get_top_post(self, subreddit):
"""
Return a pre-formatted string with top post title, author,
and subreddit name from the subreddit passed as the only required
argument.
:param subreddit: A valid subreddit name
:type subreddit: str
:return: A string with top post title, author,
and subreddit name from that subreddit.
:rtype: str
"""
url = "https://www.reddit.com/r/{}.json?limit=1".format(subreddit)
headers = {'User-Agent': 'nikolak#outlook.com tutorial code'}
request = urllib.request.Request(url, header=headers)
response = urllib.request.urlopen(request)
data = json.load(response)
top_post = data['data']['children'][0]['data']
return "'{title}' by {author} in {subreddit}".format(**top_post)
def run(self):
"""
Go over every item in the self.subreddits list
(which was supplied during __init__)
and for every item assume it's a string with valid subreddit
name and fetch the top post using the _get_top_post method
from reddit. Store the result in a local variable named
top_post and then emit a pyqtSignal add_post(QString) where
QString is equal to the top_post variable that was set by the
_get_top_post function.
"""
for subreddit in self.subreddits:
top_post = self._get_top_post(subreddit)
self.emit(pyqtSignal('add_post(QString)'), top_post)
self.sleep(2)
class ThreadingTutorial(QtWidgets.QMainWindow, newdesign.Ui_MainWindow):
"""
How the basic structure of PyQt GUI code looks and behaves like is
explained in this tutorial
http://nikolak.com/pyqt-qt-designer-getting-started/
"""
def __init__(self):
super(self.__class__, self).__init__()
self.setupUi(self)
self.btn_start.clicked.connect(self.start_getting_top_posts)
def start_getting_top_posts(self):
# Get the subreddits user entered into an QLineEdit field
# this will be equal to '' if there is no text entered
subreddit_list = str(self.edit_subreddits.text()).split(',')
if subreddit_list == ['']: # since ''.split(',') == [''] we use that to check
# whether there is anything there to fetch from
# and if not show a message and abort
QtWidgets.QMessageBox.critical(self, "No subreddits",
"You didn't enter any subreddits.",
QtWidgets.QMessageBox.Ok)
return
# Set the maximum value of progress bar, can be any int and it will
# be automatically converted to x/100% values
# e.g. max_value = 3, current_value = 1, the progress bar will show 33%
self.progress_bar.setMaximum(len(subreddit_list))
# Setting the value on every run to 0
self.progress_bar.setValue(0)
# We have a list of subreddits which we use to create a new getPostsThread
# instance and we pass that list to the thread
self.get_thread = getPostsThread(subreddit_list)
# Next we need to connect the events from that thread to functions we want
# to be run when those pyqtSignals get fired
# Adding post will be handeled in the add_post method and the pyqtSignal that
# the thread will emit is pyqtSignal("add_post(QString)")
# the rest is same as we can use to connect any pyqtSignal
self.connect(self.get_thread, pyqtSignal("add_post(QString)"), self.add_post)
# This is pretty self explanatory
# regardless of whether the thread finishes or the user terminates it
# we want to show the notification to the user that adding is done
# and regardless of whether it was terminated or finished by itself
# the finished pyqtSignal will go off. So we don't need to catch the
# terminated one specifically, but we could if we wanted.
self.connect(self.get_thread, pyqtSignal("finished()"), self.done)
# We have all the events we need connected we can start the thread
self.get_thread.start()
# At this point we want to allow user to stop/terminate the thread
# so we enable that button
self.btn_stop.setEnabled(True)
# And we connect the click of that button to the built in
# terminate method that all QThread instances have
self.btn_stop.clicked.connect(self.get_thread.terminate)
# We don't want to enable user to start another thread while this one is
# running so we disable the start button.
self.btn_start.setEnabled(False)
def add_post(self, post_text):
"""
Add the text that's given to this function to the
list_submissions QListWidget we have in our GUI and
increase the current value of progress bar by 1
:param post_text: text of the item to add to the list
:type post_text: str
"""
self.list_submissions.addItem(post_text)
self.progress_bar.setValue(self.progress_bar.value()+1)
def done(self):
"""
Show the message that fetching posts is done.
Disable Stop button, enable the Start one and reset progress bar to 0
"""
self.btn_stop.setEnabled(False)
self.btn_start.setEnabled(True)
self.progress_bar.setValue(0)
QtWidgets.QMessageBox.information(self, "Done!", "Done fetching posts!")
def main():
app = QtWidgets.QApplication(sys.argv)
form = ThreadingTutorial()
form.show()
app.exec_()
if __name__ == '__main__':
main()
Now I'm getting the following error:
AttributeError: 'ThreadingTutorial' object has no attribute 'connect'
Can anyone please tell me how to fix this? Any help would be, as always, very much appreciated.
Using QObject.connect() and similar in PyQt4 is known as "Old style signals", and is not supported in PyQt5 anymore, it supports only "New style signals", which already in PyQt4 was the recommended way to connect signals.
In PyQt5 you need to use the connect() and emit() methods of the bound signal directly, e.g. instead of:
self.emit(pyqtSignal('add_post(QString)'), top_post)
...
self.connect(self.get_thread, pyqtSignal("add_post(QString)"), self.add_post)
self.connect(self.get_thread, pyqtSignal("finished()"), self.done)
use:
self.add_post.emit(top_post)
...
self.get_thread.add_post.connect(self.add_post)
self.get_thread.finished.connect(self.done)
However for this to work you need to explicitly define the add_post signal on your getPostsThread first, otherwise you'll get an attribute error.
class getPostsThread(QThread):
add_post = pyqtSignal(str)
...
In PyQt4 with old style signals when a signal was used it was automatically defined, this now needs to be done explicitly.
I am trying to write a basic program using leap motion, I just want to constantly run the on_frame method but the method only runs once and disconnecting the device does not call the on_disconnect method. The program will not run until I hit enter, What am I doing wrong? Thanks for the help :
import Leap, sys, thread
from Leap import CircleGesture, KeyTapGesture, ScreenTapGesture,SwipeGesture
class LeapMotionListener(Leap.Listener):
state_names = ["STATE_INVAILD","STATE_START","STATE_UPDATE", "STATE_END"]
def on_init(self, controller):
print "Initialized"
def on_connect(self, controller):
print "Connected"
controller.enable_gesture(Leap.Gesture.TYPE_CIRCLE);
controller.enable_gesture(Leap.Gesture.TYPE_KEY_TAP);
controller.enable_gesture(Leap.Gesture.TYPE_SCREEN_TAP);
controller.enable_gesture(Leap.Gesture.TYPE_SWIPE);
print "All gestures enabled"
def on_disconnect(self, controller):
print "Disconnected"
def on_exit(self, controller):
print "Exit"
def on_frame(self, controller):
frame= controller.frame()
print "\n Frame ID"+ str(frame.id)
print "num of hands: " +str(len(frame.hands))
print "num of gestures: " +str(len(frame.gestures()))
for gesture in frame.gestures():
if gesture.type is Leap.Gesture.TYPE_CIRCLE:
circle = Leap.CircleGesture(gesture)
elif gesture.type is Leap.Gesture.TYPE_SWIPE:
swipe = Leap.SwipeGesture(gesture)
elif gesture.type is Leap.Gesture.TYPE_KEY_TAP:
key_tap = Leap.KeyTapGesture(gesture)
elif gesture.type is Leap.Gesture.TYPE_SCREEN_TAP:
screen_tap = Leap.ScreenTapGesture(gesture)
def main():
listener= LeapMotionListener()
controller = Leap.Controller()
controller.add_listener(listener)
print "Press enter to quit: "
try:
sys.stdin.readline()
except KeyboardInterrupt:
pass
finally:
controller.remove_listener(listener)
if __name__ == "__main__":
main()
Your code runs fine from the command line. I.e:
> python scriptname.py
Are you running from Idle? if so, this part:
try:
sys.stdin.readline()
except KeyboardInterrupt:
pass
doesn't work. (See Python 3.2 Idle vs terminal) A similar issue might exist in other IDEs.
The following should work in Idle, but you have to use Ctrl-C to exit.
# Keep this process running until a Ctrl-C is pressed
print "Press Ctrl-C to quit..."
try:
while True:
time.sleep(1)
except:
print "Quiting"
finally:
# Remove the sample listener when done
controller.remove_listener(listener)
Quitting on any key stroke in both Idle and the command line seemed surprisingly difficult and complex when I tried it some time ago -- but then, I'm a Python duffer.
This is my code :-
from javax.swing import *
class Example(JFrame):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
panel = JPanel()
panel.setLayout(None)
self.getContentPane().add(panel)
panel.setLayout(None)
area = JTextField('',15)
panel.add(JLabel("username:", SwingConstants.RIGHT))
panel.add(area)
self.setTitle("Quit button")
self.setSize(600, 400)
self.setLocationRelativeTo(None)
self.setVisible(True)
def onQuit(self, e):
System.exit(0)
if __name__ == '__main__':
Example()
Here I am just trying to make of use JTextField() so that I can get some input from the user. But after running it, the window was blank, there was no text field on the window. I ran it in sikuli r930 on windows 7. Could anyone tell me what has gone wrong??
I think there is a problem with layout in your code. Try to set some layout instead of "None". Fixed initUI function could look like this:
def initUI(self):
panel = JPanel()
panel.setLayout(FlowLayout(FlowLayout.CENTER,1,150))
self.getContentPane().add(panel)
area = JTextField('',15)
panel.add(JLabel("username:", SwingConstants.RIGHT))
panel.add(area)
self.setTitle("Quit button")
self.setSize(600, 400)
self.setLocationRelativeTo(None)
self.setVisible(True)
Additional import line is needed in this case:
from java.awt import FlowLayout