how to make blinking label or widget with pyqt4 - pyqt4

Hi i would like to know if we can make a label blinking with pyqt 4 my goal is to create a waring label , saying waring missing folder and make it blinking I dont have any code and I am new with PyQt if it not label it can be widget or anything please not message box and thanks for the help

Disclaimer: I have pyqt5 installed and converted it to pyqt4 without testing it in pyqt4...
class MyForm(QtGui.QWidget):
def __init__(self, parent = None):
super(MyForm, self).__init__(parent)
self.lbl = QtGui.QLabel("Clock", self)
self.lbl.setAlignment(QtCore.Qt.AlignCenter)
self.lblHidden = False
vLayout = QtGui.QVBoxLayout(self)
vLayout.addWidget(self.lbl)
self.setLayout(vLayout)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.flashLbl)
timer.start(1000)
def flashLbl(self):
if self.lblHidden == False:
self.lbl.hide()
self.lblHidden = True
else:
self.lbl.show()
self.lblHidden = False

Related

Python 3 Wx Change tray icon

I'm using WxPython (phoenix new version) to have an icon on the tray bar while the programs runs, but I would some events to change the icon used.
I found this great example to get things started: Quick and easy: trayicon with python?
But it doesn't have the example to cycle through icons.
Just after the imports it has this line:
TRAY_ICON = 'icon.png'
And I've tried to use that as sort of a variable, and adding the following line to an event (it has some mock events like hellow world on a right click
TRAY_ICON = 'icon2.png'
but it didn't work =//
I only found examples in c, and one in python but using a very complex win32 alternative that I can't figure out
This should provide you with enough to solve your problem.
import wx
import wx.adv
ICON = 'toggle1.png'
ICONS = ["toggle1.png", "toggle2.png"]
X=[1,0]
class TaskBarIcon(wx.adv.TaskBarIcon):
def __init__(self, frame):
self.frame = frame
self.toggle = 0
wx.adv.TaskBarIcon.__init__(self)
self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN, self.OnToggle)
self.OnSetIcon(ICON)
def CreatePopupMenu(self):
menu = wx.Menu()
togglem = wx.MenuItem(menu, wx.NewId(), 'Toggle Icon')
menu.Bind(wx.EVT_MENU, self.OnToggle, id=togglem.GetId())
menu.Append(togglem)
menu.AppendSeparator()
flashm = wx.MenuItem(menu, wx.NewId(), 'Flash Icon')
menu.Bind(wx.EVT_MENU, self.OnTimer, id=flashm.GetId())
menu.Append(flashm)
menu.AppendSeparator()
quitm = wx.MenuItem(menu, wx.NewId(), 'Quit')
menu.Bind(wx.EVT_MENU, self.OnQuit, id=quitm.GetId())
menu.Append(quitm)
return menu
def OnSetIcon(self, path):
icon = wx.Icon(path)
self.SetIcon(icon, path)
def OnToggle(self, event):
self.toggle=X[self.toggle]
use_icon = ICONS[self.toggle]
self.OnSetIcon(use_icon)
def OnTimer(self,event):
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnInUseTimer)
self.timer.Start(1000)
def OnInUseTimer(self,event):
self.OnToggle(None)
def OnQuit(self, event):
self.RemoveIcon()
wx.CallAfter(self.Destroy)
self.frame.Close()
if __name__ == '__main__':
app = wx.App()
frame=wx.Frame(None)
TaskBarIcon(frame)
app.MainLoop()
and the images:
In action:

Using dynamically added widgets in PyQt/Pyside

I have modified the answer given here as written below. The code is basically creating pushbuttons with a counter as pushButton_0, pushButton_1..
Here, I know that when I press to self.addButton I am creating widgets named like self.pushButton_0, self.pushButton_1 etc. So, my question is, how I'm supposed to use this pushbuttons? Because when I'm trying to do something like self.pushButton_0.clicked.connect(self.x), it' s telling me that "there is no attribute named 'pushButton_0'".
Thanks!
from PyQt4 import QtGui, QtCore
import sys
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__()
self.GUI()
def GUI(self):
self.count = 0
# main button
self.addButton = QtGui.QPushButton('button to add other widgets')
self.addButton.clicked.connect(self.addWidget)
# scroll area widget contents - layout
self.scrollLayout = QtGui.QFormLayout()
# scroll area widget contents
self.scrollWidget = QtGui.QWidget()
self.scrollWidget.setLayout(self.scrollLayout)
# scroll area
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.scrollWidget)
# main layout
self.mainLayout = QtGui.QVBoxLayout()
# add all main to the main vLayout
self.mainLayout.addWidget(self.addButton)
self.mainLayout.addWidget(self.scrollArea)
# central widget
self.centralWidget = QtGui.QWidget()
self.centralWidget.setLayout(self.mainLayout)
# set central widget
self.setCentralWidget(self.centralWidget)
def addWidget(self):
self.scrollLayout.addRow(Test(self))
self.count = self.count + 1
print(self.count)
class Test(QtGui.QWidget):
def __init__( self, main):
super(Test, self).__init__()
self.Main = main
self.setup()
def setup(self):
print(self.Main.count)
name = "pushButton_"+str(self.Main.count)
print(name)
self.name = QtGui.QPushButton('I am in Test widget '+str(self.Main.count))
layout = QtGui.QHBoxLayout()
layout.addWidget(self.name)
self.setLayout(layout)
app = QtGui.QApplication(sys.argv)
myWidget = Main()
myWidget.show()
app.exec_()
After hours, I found the problem!
You have to declare the signal while creating the pushbutton!
To fix this, I rewrote the setup function as below;
def setup(self):
print(self.Main.count)
name = "pushButton_"+str(self.Main.count)
print(name)
self.name = QtGui.QPushButton('I am in Test widget '+str(self.Main.count))
self.name.clicked.connect(self.x) # self.x is any function
layout = QtGui.QHBoxLayout()
layout.addWidget(self.name)
self.setLayout(layout)
So know, you will run function x whenever you push the new created pushbuttons!

Overriding QLabel widget in PyQT

I am new to PyQt perhaps thats why facing this issue. I am trying to make a component inserter for excel sheets. For this purpose I am using QT for interface and using Qlabels within parent class of QMainWindow. On the basis of item selected from Qlist Widget, few Qlabels have to change on mainwindow dynamically Component inserter
As can be seen in above picture, the labels like WCAP-; Part Number and all below needs to change dynamically when the selected items change(when select button is clicked). But what happening is if I choose a different item from list, the previous Label stays and the new label is overlapping it as can be seen from picture below showing overlapping of labels
The code below shows that whenever button "Select" is pressed", label2 (Qlabel2) is formed, how can i delete the previous label whenever select button is pressed so that new Label dynamically replaces the old label.
Thanks a lot in advance.
def Display(self):
self.close()
label1 = QtGui.QLabel("Select the sheet",self)
label1.move(0,15)
self.listwidget = QtGui.QListWidget(self)
self.listwidget.move(0,40)
self.listwidget.resize(150,150)
for i in range(len(self.sheetnames)):
self.listwidget.addItem("%s"%self.sheetnames[i])
btn = QtGui.QPushButton('Select',self)
btn.resize(50,50)
btn.move(170,40)
btn.clicked.connect(self.Selected)
self.show()
def Selected(self):
self.close()
selecteditem = self.listwidget.currentItem().text()
self.sheetindex = self.sheetnames.index(selecteditem)
print self.sheetindex
aa = self.loadsheet.sheet_by_name(selecteditem)
global label2
label2 = QtGui.QLabel("",self)
label2.setText(selecteditem)
label2.move(0,190)
self.show()
self.InputParameters(aa)
You see a new QLabel because you create a new one every time you call Selected. I would initiate the UI at the creation of the widget (in the __init__ method):
def __init__(self):
self.label2 = QtGui.QLabel("",self)
And only update the text of the Qlabel when Selected is executed:
def Selected(self):
self.label2.setText(selecteditem)
About reinitializing all labels with an unknown number of labels and removing the old ones, you might want to look at QLabel.setParent(None). I wrote you a little example:
from PyQt4 import QtGui, QtCore
import sys
class test(QtGui.QWidget):
def __init__(self,parent=None):
self.widget=QtGui.QWidget.__init__(self, parent)
# Button to add labels
self.btnAdd = QtGui.QPushButton('Add')
self.btnAdd.connect(self.btnAdd, QtCore.SIGNAL('clicked()'),self.btnAddPressed)
# Button to remove labels
self.btnRemove = QtGui.QPushButton('Remove')
self.btnRemove.connect(self.btnRemove, QtCore.SIGNAL('clicked()'), self.btnRemovePressed)
# List to keep track of labels
self.labels=[]
# Layout
self.hbox = QtGui.QHBoxLayout()
self.hbox.addWidget(self.btnAdd)
self.hbox.addWidget(self.btnRemove)
self.setLayout(self.hbox)
self.show()
def btnAddPressed(self):
"""Adds a new label."""
self.labels.append(QtGui.QLabel("lbl"+str(len(self.labels)+1), self))
self.hbox.addWidget(self.labels[-1])
def btnRemovePressed(self):
"""Removes last label."""
self.labels[-1].setParent(None)
self.labels.pop(-1)
def main():
#Creating application
app = QtGui.QApplication(sys.argv)
main_win = test()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

How do I thread a single method on a PyQt GUI so that the rest of the GUI is still accessible?

Basically, when the Switch Button is pressed, which is connected to the reconfigure method, I want everything in the reconfigure method to run as a separate thread/process so the main GUI is still accessible and not being blocked. Below is a watered down version of my code.
import sys, time
from PyQt4 import QtGui, QtCore
from PyQt4.Qt import *
#//Popup Class - Will appear when the Switch Button is pressed
class Popup(QWidget):
def __init__(self):
QWidget.__init__(self)
#//nothing here now, it will have a message telling user to wait while program is run
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
grid = QtGui.QGridLayout()
label_header = QtGui.QLabel("TEST RECONFIGURE")
font = label_header.font()
font.setPointSize(24)
label_header.setFont(font)
#//Creating Static Labels that will be placed in the GUI
label_1 = QtGui.QLabel("Menu 1:")
label_2 = QtGui.QLabel("Menu 2:")
label_spacer = QtGui.QLabel("")
label_cfg = QtGui.QLabel("Current Configuration: '/tmp/directory_here' ")
global comboBox1
comboBox1 = QtGui.QComboBox()
comboBox1.addItem("1")
comboBox1.addItem("2")
global comboBox2
comboBox2 = QtGui.QComboBox()
comboBox2.addItem("3")
comboBox2.addItem("4")
#//Switch Button!!!
global switchButton
switchButton = QPushButton("Switch")
switchButton.clicked.connect(self.reconfigure)
quitButton = QtGui.QPushButton('Quit')
quitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)
#//Configure the grid layout
grid.addWidget(label_spacer, 0,0,9,9)
grid.addWidget(label_header, 0,0,1,6)
grid.addWidget(label_1, 1,0,1,1)
grid.addWidget(comboBox1, 2,0,1,1)
grid.addWidget(label_2, 3,0,1,1)
grid.addWidget(comboBox2, 4,0,1,1)
grid.addWidget(switchButton, 5,0,1,2)
grid.addWidget(label_cfg, 6,0,1,9)
grid.addWidget(quitButton, 9,9,1,1)
self.setLayout(grid)
self.setGeometry(640,300,400,600)
self.show()
#//open up the popup window for switch button, and reconfigure
def reconfigure(self):
print "Opening New Window"
self.w = Popup()
self.w.setGeometry(QRect(self.x()+100,self.y()+100,400,200))
self.w.show()
txt1 = str(comboBox1.currentText())
txt2 = str(comboBox2.currentText())
print " reconfiguring to option %s and option %s" %(txt1, txt2)
#
# This is where most of the work is done, and takes about 1/2 an hour for everything to run
# Want to make this method a separate thread/process so the rest of the main GUI is still accessible
# while the program is running as the whole class will be a separate tab in a larger GUI
#
print "all done!"
#//runner
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I feel like I have to use threading and signals to accomplish this, but I am not having much luck. Any help would be greatly appreciated. Thank you!
import sys, time
from PyQt4 import QtGui, QtCore
from PyQt4.Qt import *
class ConfigureThread(QtCore.QThread):
def run(self):
pass
#
# This is where most of the work is done, and takes about 1/2 an hour for everything to run
# Want to make this method a separate thread/process so the rest of the main GUI is still accessible
# while the program is running as the whole class will be a separate tab in a larger GUI
#
#//Popup Class - Will appear when the Switch Button is pressed
class Popup(QWidget):
def __init__(self):
QWidget.__init__(self)
#//nothing here now, it will have a message telling user to wait while program is run
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
grid = QtGui.QGridLayout()
label_header = QtGui.QLabel("TEST RECONFIGURE")
font = label_header.font()
font.setPointSize(24)
label_header.setFont(font)
#//Creating Static Labels that will be placed in the GUI
label_1 = QtGui.QLabel("Menu 1:")
label_2 = QtGui.QLabel("Menu 2:")
label_spacer = QtGui.QLabel("")
label_cfg = QtGui.QLabel("Current Configuration: '/tmp/directory_here' ")
global comboBox1
comboBox1 = QtGui.QComboBox()
comboBox1.addItem("1")
comboBox1.addItem("2")
global comboBox2
comboBox2 = QtGui.QComboBox()
comboBox2.addItem("3")
comboBox2.addItem("4")
#//Switch Button!!!
global switchButton
switchButton = QPushButton("Switch")
switchButton.clicked.connect(self.reconfigure)
quitButton = QtGui.QPushButton('Quit')
quitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)
#//Configure the grid layout
grid.addWidget(label_spacer, 0,0,9,9)
grid.addWidget(label_header, 0,0,1,6)
grid.addWidget(label_1, 1,0,1,1)
grid.addWidget(comboBox1, 2,0,1,1)
grid.addWidget(label_2, 3,0,1,1)
grid.addWidget(comboBox2, 4,0,1,1)
grid.addWidget(switchButton, 5,0,1,2)
grid.addWidget(label_cfg, 6,0,1,9)
grid.addWidget(quitButton, 9,9,1,1)
self.setLayout(grid)
self.setGeometry(640,300,400,600)
self.show()
#//open up the popup window for switch button, and reconfigure
def reconfigure(self):
print("Opening New Window")
self.w = Popup()
self.w.setGeometry(QRect(self.x()+100,self.y()+100,400,200))
self.w.show()
txt1 = str(comboBox1.currentText())
txt2 = str(comboBox2.currentText())
print(" reconfiguring to option %s and option %s" %(txt1, txt2))
self.th = ConfigureThread()
self.th.finished.connect(self.configuring_done)
self.th.start()
def configuring_done(self):
print("all done!")
#//runner
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

wxpython run when textctrl changes

I am making a simple text editor in wxpython. I would like it to be able to edit code such as python, and as such I would like to have it highlight the text in a similar manner to IDLE or Notepad++. I know how I would highlight it, but I would like the best way of running it. I don't know if it is possible but what I would really like is to run whenever a key is pressed, and not on a loop checking if it is pressed, so as to save on processing.
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(500,600))
style = wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_RICH2
self.status_area = wx.TextCtrl(self, -1,
pos=(10, 270),style=style,
size=(380,150))
self.status_area.AppendText("Type in your wonderfull code here.")
fg = wx.Colour(200,80,100)
at = wx.TextAttr(fg)
self.status_area.SetStyle(3, 5, at)
self.CreateStatusBar() # A Statusbar in the bottom of the window
# Setting up the menu.
filemenu= wx.Menu()
filemenu.Append(wx.ID_ABOUT, "&About","Use to edit python code")
filemenu.AppendSeparator()
filemenu.Append(wx.ID_EXIT,"&Exit"," Terminate the program")
# Creating the menubar.
menuBar = wx.MenuBar()
menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
self.SetMenuBar(menuBar) # Adding the MenuBar to the Frame content.
self.Show(True)
app = wx.App(False)
frame = MainWindow(None, "Python Coder")
app.MainLoop()
If a loop is needed what would be the best way to make it loop, with a while loop, or a
def Loop():
<code>
Loop()
My new code with the added bind:
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(500,600))
style = wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_RICH2
self.status_area = wx.TextCtrl(self, -1,
pos=(10, 270),style=style,
size=(380,150))
#settup the syntax highlighting to run on a key press
self.Bind(wx.EVT_CHAR, self.onKeyPress, self.status_area)
self.status_area.AppendText("Type in your wonderfull code here.")
fg = wx.Colour(200,80,100)
at = wx.TextAttr(fg)
self.status_area.SetStyle(3, 5, at)
self.CreateStatusBar() # A Statusbar in the bottom of the window
# Setting up the menu.
filemenu= wx.Menu()
filemenu.Append(wx.ID_ABOUT, "&About","Use to edit python code")
filemenu.AppendSeparator()
filemenu.Append(wx.ID_EXIT,"&Exit"," Terminate the program")
# Creating the menubar.
menuBar = wx.MenuBar()
menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
self.SetMenuBar(menuBar) # Adding the MenuBar to the Frame content.
self.Show(True)
def onKeyPress (self, event):
print "KEY PRESSED"
kc = event.GetKeyCode()
if kc == WXK_SPACE or kc == WXK_RETURN:
Line = self.status_area.GetValue()
print Line
app = wx.App(False)
frame = MainWindow(None, "Python Coder")
app.MainLoop()
In your MainWindow __init__ function add this
self.Bind(wx.EVT_CHAR, self.onKeyPress, self.status_area)
then define onKeyPress in MainWindow
def onKeyPress (self, event):
kc = event.GetKeyCode()
if kc == WXK_SPACE or kc == WXK_RETURN:
#Run your highlighting code here
Come to think of it, this might not be the most efficient way of doing code highlighting. Let me look this up. But in the meantime you can try this.
Edit:
Take a look at this - StyledTextCtrl . I think its more along the lines of what you need.
I solved this when I faced the same issue by creating a custom event.
First, I created a subclass of the TextCtrl, so I had a place in code to raise/post the custom event from:
import wx.lib.newevent
(OnChangeEvent, EVT_VALUE_CHANGED) = wx.lib.newevent.NewEvent()
class TextBox(wx.TextCtrl):
old_value = u''
def __init__(self,*args,**kwargs):
wx.TextCtrl.__init__(self,*args,**kwargs)
self.Bind(wx.EVT_SET_FOCUS, self.gotFocus) # used to set old value
self.Bind(wx.EVT_KILL_FOCUS, self.lostFocus) # used to get new value
def gotFocus(self, evt):
evt.Skip()
self.old_value = self.GetValue()
def lostFocus(self, evt):
evt.Skip()
if self.GetValue() != self.old_value:
evt = OnChangeEvent(oldValue=self.old_value, newValue=self.GetValue())
wx.PostEvent(self, evt)
Now, in my frame's code, here is a snippet of me Binding the event, and using it.
summ_text_ctrl = TextBox(self, -1, size=(400, -1))
summ_text_ctrl.Bind(EVT_VALUE_CHANGED, self.onTextChanged)
def OnTextChanged(self, evt):
evt.Skip()
print('old Value: %s' % evt.oldValue )
print('new Value: %s' % evt.newValue )

Resources