How to shift position of radio button and reverse radio button function when unchecking it? - pyqt4

I would like to ask 2 questions about my code. First, how do I shift the position of my radio button into the position that I want (I wrote it in the code)? And how do I reverse my LCD screen after unchecking it? Right now, it shows '02' when checked but I want to reverse the process when I uncheck it. Any solution?
class MyRadioButton(QtGui.QRadioButton):
def __init__(self):
super(MyRadioButton, self).__init__()
self.value = None
def SetValue(self, val):
self.value = val
def GetValue(self):
return self.value
class UserTool(QtGui.QDialog):
def __init__(self, parent = None):
super(UserTool, self).__init__()
self.layout = QtGui.QVBoxLayout(self)
self.setup(self)
def setup(self, Dialog):
Dialog.setObjectName(_fromUtf8("Dialog"))
self.resize(688, 677)
self.lcdNumber = QtGui.QLCDNumber(Dialog)
self.lcdNumber.setGeometry(QtCore.QRect(590, 10, 71, 23))
self.lcdNumber.setFrameShadow(QtGui.QFrame.Raised)
self.lcdNumber.setObjectName(_fromUtf8("lcdNumber"))
self.lcdNumber.setStyleSheet("* {background-color: black; color: white;}")
self.lcdNumber.display("00")
self.radioButton_8 = MyRadioButton()
self.radioButton_8.setText("A1")
self.radioButton_8.SetValue("02")
self.radioButton_8.toggled.connect(self.showValueFromRadioButtonToLCDNumber)
self.layout.addWidget(self.radioButton_8)
#self.radioButton_8 = QtGui.QRadioButton(Dialog)
self.radioButton_8.setGeometry(QtCore.QRect(460, 10, 82, 17))
self.radioButton_8.setChecked(False)
self.radioButton_8.setAutoExclusive(False)
self.radioButton_8.setObjectName(_fromUtf8("radioButton_8"))
def retranslateUi(self, Dialog):
self.radioButton_8.setText(_translate("Dialog", "A1", None))
def showValueFromRadioButtonToLCDNumber(self):
value = self.radioButton_8.GetValue()
if self.radioButton_8.isChecked():
self.lcdNumber.display(value)

Here is working example. In order to show previous value you need mechanism to cash that value before it is changed. To shift radioButton I use addSpacing()
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import Qt
class MyRadioButton(QtGui.QRadioButton):
def __init__(self):
super(MyRadioButton, self).__init__()
self.value = None
def SetValue(self, val):
self.value = val
def GetValue(self):
return self.value
class Widget(QtGui.QWidget):
def __init__(self):
super(Widget, self).__init__()
self.layout = QtGui.QVBoxLayout(self)
self.radioButton = MyRadioButton()
self.radioButton.setText("some text")
self.radioButton.SetValue("02")
self.radioButton.toggled.connect(self.showValueFromRadioButtonToLCDNumber)
self.lcdNumber = QtGui.QLCDNumber()
self.lcdNumber.display("-2")# previous value
self.layoutHorizontal = QtGui.QHBoxLayout(self)
self.layoutHorizontal.addSpacing(20)# add space before radioButton
self.layoutHorizontal.addWidget(self.radioButton)
self.layout.addLayout(self.layoutHorizontal)
self.layout.addWidget(self.lcdNumber)
self.previousValue = ""
def showValueFromRadioButtonToLCDNumber(self):
value = self.radioButton.GetValue()
if self.radioButton.isChecked():
self.previousValue = self.lcdNumber.value()# save previous value before it is changed
self.lcdNumber.display(value)
else:
self.lcdNumber.display(self.previousValue)

Related

How to add scrollable regions with Drag & drop widgets with PyQt?

Please add a scrollable region to this code so that when I run the code, I can scroll down through the window and see the last items in the window and replace them.
As this is a drag and drop code I could not add scroll to it.
Moreover, during the drag and drop process, the scroll should work and does not interrupt the drag and drop process.
from PyQt5.QtWidgets import QApplication, QScrollArea, QHBoxLayout, QWidget, QLabel, QMainWindow, QVBoxLayout
from PyQt5.QtCore import Qt, QMimeData, pyqtSignal
from PyQt5.QtGui import QDrag, QPixmap
class DragItem(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setContentsMargins(25, 5, 25, 5)
self.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.setStyleSheet("border: 1px solid black;")
# Store data separately from display label, but use label for default.
self.data = self.text()
def set_data(self, data):
self.data = data
def mouseMoveEvent(self, e):
if e.buttons() == Qt.LeftButton:
drag = QDrag(self)
mime = QMimeData()
drag.setMimeData(mime)
pixmap = QPixmap(self.size())
self.render(pixmap)
drag.setPixmap(pixmap)
drag.exec_(Qt.MoveAction)
class DragWidget(QWidget):
"""
Generic list sorting handler.
"""
orderChanged = pyqtSignal(list)
def __init__(self, *args, orientation=Qt.Orientation.Horizontal, **kwargs):
super().__init__()
self.setAcceptDrops(True)
# Store the orientation for drag checks later.
self.orientation = orientation
if self.orientation == Qt.Orientation.Vertical:
self.blayout = QVBoxLayout()
else:
self.blayout = QHBoxLayout()
self.setLayout(self.blayout)
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
pos = e.pos()
widget = e.source()
for n in range(self.blayout.count()):
# Get the widget at each index in turn.
w = self.blayout.itemAt(n).widget()
if self.orientation == Qt.Orientation.Vertical:
# Drag drop vertically.
drop_here = pos.y() < w.y() + w.size().height() // 2
else:
# Drag drop horizontally.
drop_here = pos.x() < w.x() + w.size().width() // 2
if drop_here:
# We didn't drag past this widget.
# insert to the left of it.
self.blayout.insertWidget(n-1, widget)
self.orderChanged.emit(self.get_item_data())
break
e.accept()
def add_item(self, item):
self.blayout.addWidget(item)
def get_item_data(self):
data = []
for n in range(self.blayout.count()):
# Get the widget at each index in turn.
w = self.blayout.itemAt(n).widget()
data.append(w.data)
return data
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.drag = DragWidget(orientation=Qt.Orientation.Vertical)
self.scroll = QScrollArea() ###########
self.blayout = QHBoxLayout()
self.widget = QWidget()
for n, l in enumerate(['Art', 'Boo', 'EOA', 'Hel', \
'Hyg', 'Lei', 'Lei','Lei','Lei','Lei','Lei','Lei','Lei','Lei','Lei','Lei','Lei', 'Med',\
'Nut','Nut','Nut','Rel','Rel','Rel','Sle','SLN','Spo','Spo','Spo','Spo','Spo','Thi','Thi',\
'Wor','Wor','Wor','Wor','Wor','Wor','Wor','Wor','Wor','Wor','Wor','Wor','Wor','Wor']):
item = DragItem(l)
item.set_data(n) # Store the data.
self.drag.add_item(item)
def myFun():
print('hi', self.drag.get_item_data())
# Print out the changed order.
# self.drag.orderChanged.connect(print)
# add by me
self.drag.orderChanged.connect(myFun)
#Scroll Area Properties
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.widget)
container = QWidget()
layout = QVBoxLayout()
layout.addStretch(1)
layout.addWidget(self.drag)
layout.addStretch(1)
container.setLayout(layout)
self.setCentralWidget(container)
# self.setCentralWidget(self.scroll)
app = QApplication([])
w = MainWindow()
w.show()
app.exec_()

PyQt5 button "clicked.connect()" not working when importing from class

I am running a test for clicked.connect failing issue.
I want to wrap all the widgets in the CentralWidget to a class called React. When I call React in CentralWidget, widgets like Button, self.writeLine and self.valLabel will show up, but when I pressed the react Button, it's not functioning, which is to update self.valLabel according to self.writeLine.
A snap shot: Buttom not working
I suspect that
Button.clicked.connect(self.BottomPressedTest) # no function when pressed
is not doing what is supposed to do. But have no clue why this is happening.
The entire test code is shown below,
from PyQt5 import QtCore, QtWidgets, QtGui
import sys
class CentralWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(CentralWidget, self).__init__(parent)
self.mainLayout = QtWidgets.QGridLayout()
self.setLayout(self.mainLayout)
panel = React(1).groupbox
self.mainLayout.addWidget(panel, 0, 0)
class React(QtWidgets.QGroupBox):
def __init__(self, ch):
self.value = 0
self.groupbox = QtWidgets.QGroupBox()
self.vbox = QtWidgets.QVBoxLayout()
self.groupbox.setLayout(self.vbox)
Button = QtWidgets.QPushButton('React')
Button.clicked.connect(self.BottomPressedTest) # no function when pressed
self.writeLine = QtWidgets.QSpinBox()#QLineEdit()
self.writeLine.setFont(QtGui.QFont('Arial', 16))
self.valLabel = QtWidgets.QLabel()
self.valLabel.setFont(QtGui.QFont('Arial', 20))
self.valLabel.setText(f'React: {self.value}')
self.vbox.addWidget(Button)
self.vbox.addWidget(self.valLabel)
self.vbox.addWidget(self.writeLine)
def BottomPressedTest(self):
print('React bottom pressed.')
self.valLabel.setText(f'React: {self.writeLine.text()}')
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setWindowTitle(QtCore.QCoreApplication.applicationName())
self.centralWidget = CentralWidget()
self.setCentralWidget(self.centralWidget)
class MainApplication(QtWidgets.QApplication):
def __init__(self, argv: list):
super(MainApplication, self).__init__(argv)
self.mainWindow = MainWindow()
self.mainWindow.resize(200,200)
self.mainWindow.raise_()
self.mainWindow.show()
def main():
application = MainApplication([])
sys.exit(application.exec_())
if __name__ == "__main__":
main()
Edit
I changed the first few line in React to
class React(QtWidgets.QGroupBox):
def __init__(self, ch):
super().__init__()
self.value = 0
self.setStyleSheet('QGroupBox { color: white; border: 3px solid grey; }') #
self.vbox = QtWidgets.QVBoxLayout()
self.setLayout(self.vbox)
, and then change CentralWidget to
class CentralWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(CentralWidget, self).__init__(parent)
self.mainLayout = QtWidgets.QGridLayout()
self.setLayout(self.mainLayout)
panel = React(1)
self.mainLayout.addWidget(panel)
Now the problem is solved. Many thanks to #musicamante and #Passerby
Your React object is thrown away at the end of CentralWidget.__init__, with only the QGroupBox persisting. Save it in an attribute and your problem will be solved.
Note that your React object inherits from QGroupBox, but does not call its __init__ method, instead creating a new QGroupBox as a member.

How to save selected input from a drop-down box with checkboxes? My drop-down box is okay but the checkboxes are not working

Hi, I am trying to run a GUI based on wx. I made checkboxes in a drop-down list. But the checkboxes are not working. I want the checkboxes to work and save the selected input option names somewhere. Here is the code. With these selected input option names (one or more than one) I will filter a big string later. Thank you in advance :)
import wx
import wx.stc
from wx.lib.mixins.listctrl import CheckListCtrlMixin, ListCtrlAutoWidthMixin
class CheckListCtrl(wx.ListCtrl, CheckListCtrlMixin, ListCtrlAutoWidthMixin):
def __init__(self, parent):
wx.ListCtrl.__init__(self, parent, wx.ID_ANY, style=wx.LC_REPORT |
wx.SUNKEN_BORDER)
CheckListCtrlMixin.__init__(self)
ListCtrlAutoWidthMixin.__init__(self)
self.SetSize(-1, -1, -1, 50)
def OnCheckItem(self, index, flag):
item = self.GetItem(index)
if flag:
what = "checked"
else:
what = "unchecked"
print(f'{item.GetText()} - {what}')
class ListViewComboPopup(wx.ComboPopup):
def __init__(self):
wx.ComboPopup.__init__(self)
self.lc = None
def AddItem(self, txt):
self.lc.InsertItem(0, txt)
def Init(self):
self.value = -1
self.curitem = -1
def Create(self, parent):
self.lc = CheckListCtrl(parent)
self.lc.InsertColumn(0, '', width=90)
return True
def GetControl(self):
return self.lc
def OnPopup(self):
wx.ComboPopup.OnPopup(self)
def GetAdjustedSize(self, minWidth, prefHeight, maxHeight):
return wx.ComboPopup.GetAdjustedSize(
self, minWidth, 110, maxHeight)
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Popup Menu Tutorial")
panel = wx.Panel(self)
comboCtrl = wx.ComboCtrl(panel, wx.ID_ANY, "Select filter")
popupCtrl = ListViewComboPopup()
comboCtrl.SetPopupControl(popupCtrl)
popupCtrl.AddItem("mango")
popupCtrl.AddItem("cat")
popupCtrl.AddItem("dog")
popupCtrl.AddItem("tiger")
popupCtrl.AddItem("three")
popupCtrl.AddItem("hat")
popupCtrl.AddItem("hot")
popupCtrl.AddItem("sweden")
popupCtrl.AddItem("kth")
You can saev them as variables in a .txt file with pickle:
pickle.dump(your_variable, open("path/to/your/file.txt", "wb"))
and to access them:
your_variable = pickle.load(open("path/to/your/file.txt", "rb"))

pyqt5: why the mimeData().text() returns nothing?

learning PyQt5 recently, I've tried to drag a QPushButton learning this tutorial Drag & drop a button widget, and made some improvements to place the button more accurate, so I add
mime = e.mimeData().text()
x, y = mime.split(',')
according to #Avaris for this question, but I found e.mimeData().text() returned nothing which supposed to be the coordinate of local position of the cursor with respect to the button, i tried to print(mime), and got a blank line with nothing, then i print(mime.split(',')) and got ['']。
here's the code:
import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QApplication, QLabel
from PyQt5.QtCore import Qt, QMimeData
from PyQt5.QtGui import QDrag
from PyQt5 import QtCore
class Button(QPushButton):
def __init__(self, title, parent):
super().__init__(title, parent)
def mouseMoveEvent(self, e):
if e.buttons() != Qt.RightButton:
return
mimeData = QMimeData()
drag = QDrag(self)
drag.setMimeData(mimeData)
dropAction = drag.exec_(Qt.MoveAction)
def mousePressEvent(self, e):
QPushButton.mousePressEvent(self, e)
if e.button() == Qt.LeftButton:
print('press')
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setAcceptDrops(True)
self.button = Button('Button', self)
self.button.move(100, 65)
self.setWindowTitle('Click or Move')
self.setGeometry(300, 300, 280, 150)
def dragEnterEvent(self, e):
e.accept()
def dropEvent(self, e):
position = e.pos()
mime = e.mimeData().text()
x, y = mime.split(',')
#print(mime.split(','))
self.button.move(position - QtCore.QPoint(int(x), int(y)))
e.setDropAction(Qt.MoveAction)
e.accept()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
In the answer of #Avaris, you will notice they set the mimedata with the button position in the mouseMoveEvent:
mimeData = QtCore.QMimeData()
# simple string with 'x,y'
mimeData.setText('%d,%d' % (e.x(), e.y()))
The mimedata does not contain anything by default. You have to set everything yourself! Have a look at the documentation for QMimeData to see what else you can do (other than setting arbitrary text)
Drag and Drop in Camera View
def dragEnterEvent(self, event): # Drag lines
mimeData = QtCore.QMimeData()
if mimeData.hasText:
event.accept()
else:
event.ignore()
def dropEvent(self, event): # Drop lines
mimeData = QtCore.QMimeData()
format = 'application/x-qabstractitemmodeldatalist'
data=event.mimeData().data(format) # Drag Drop get data's name
name_str = codecs.decode(data,'utf-8') # Convert byte to string
mimeData.setText(name_str)
# print(name_str[26:].replace('\x00','').strip("")) # remove white space
if mimeData.hasText:
print(name_str)
# write what you will do

wxpyton - threads in many modules

I'm trying to create simple frame that will run longrun procedure, but will show counting in different window (dialog), but it don't work (staticText1 is not updating)... Here's my code:
Main frame (simple frame with one button)
import wx
import time
from threading import Thread
import Dialog1
def create(parent):
return Frame1(parent)
[wxID_FRAME1, wxID_FRAME1BUTTON1, ] = [wx.NewId() for _init_ctrls in range(2)]
class Frame1(wx.Frame):
def test1(self):
for i in range(self.delays):
time.sleep(1)
def _init_ctrls(self, prnt):
# generated method, don't edit
wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
pos=wx.Point(589, 259), size=wx.Size(178, 128),
style=wx.DEFAULT_FRAME_STYLE, title='Frame1')
self.button1 = wx.Button(id=wxID_FRAME1BUTTON1, label='button1',
name='button1', parent=self, pos=wx.Point(0, 0), size=wx.Size(178,
128), style=0)
self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button,
id=wxID_FRAME1BUTTON1)
def __init__(self, parent):
self._init_ctrls(parent)
self.delays = 5
self.timer = wx.Timer(self)
def OnButton1Button(self, event):
self.testThread = Thread(target=self.test1)
self.testThread.start()
#self.Show(False)
self.dlg = Dialog1.Dialog1(self)
self.dlg.ShowModal()
self.button1.Disable()
self.Bind(wx.EVT_TIMER, self.PollThread)
self.timer.Start(20, oneShot=True)
event.Skip()
def PollThread(self, event):
if self.testThread.isAlive():
self.Bind(wx.EVT_TIMER, self.PollThread)
self.timer.Start(200, oneShot=True)
self.dlg.staticText1.SetLabel(self.dlg.staticText1.GetLabel()+".")
else:
self.button1.Enable()
self.dlg.Destroy()
Dialog (simple dialog with one statictext):
import wx
def create(parent):
return Dialog1(parent)
[wxID_DIALOG1, wxID_DIALOG1STATICTEXT1, ] = [wx.NewId() for _init_ctrls in range(2)]
class Dialog1(wx.Dialog):
def _init_ctrls(self, prnt):
# generated method, don't edit
wx.Dialog.__init__(self, id=wxID_DIALOG1, name='', parent=prnt,
pos=wx.Point(451, 295), size=wx.Size(544, 59),
style=wx.DEFAULT_DIALOG_STYLE, title='Dialog1')
self.staticText1 = wx.StaticText(id=wxID_DIALOG1STATICTEXT1,
label=u'Please wait', name='staticText1', parent=self,
pos=wx.Point(56, 24), size=wx.Size(95, 17), style=0)
def __init__(self, parent):
self._init_ctrls(parent)

Resources