items of listwidgets in pyqt4 doesn't work properly - python

self.pushButton.clicked.connect(self.search)
def search(self):
import subprocess
keyword = str(unicode(self.lineEdit.text()))
subprocess.call(["some command"])
video_list = []
self.listWidget.clear()
video_ret = parse_vid(video_list)
self.listWidget.addItems(video_ret)
self.listWidget.itemDoubleClicked.connect(self.surf)
#######################################################################
def surf(self):
print "hello"
This code work fine for first time. But if I click pushbutton for the second time item click in listwidget gives me two execution of surf method. If I click pushbutton third time item click in listwidget execute surf method three time. Can any one help me with this weird problem??

A signal can be connected to multiple slots, in your case whenever you use the search function you are adding a new slot, it is better to add it once.
self.listWidget.itemDoubleClicked.connect(self.surf)
self.pushButton.clicked.connect(self.search)
def search(self):
import subprocess
keyword = str(unicode(self.lineEdit.text()))
subprocess.call(["some command"])
video_list = []
self.listWidget.clear()
video_ret = parse_vid(video_list)
self.listWidget.addItems(video_ret)
#######################################################################
def surf(self):
print("hello")

Related

Python CLR WinForms - Opening another from from an existing form

I am having some extreme difficulty with something so simple. All I am trying to do is launch another Windows Form from an existing Windows Form in Python. I've tried everything I can think of and I cannot figure out. Below is a example program:
import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")
clr.AddReference("System.ComponentModel")
from System.Windows.Forms import *
from System.Drawing import *
class MyForm(Form):
def __init__(self):
self.StartPosition = FormStartPosition.CenterScreen
self.btnTest = Button()
self.btnTest.Name = 'btnTest'
self.btnTest.Text = "Test"
self.btnTest.Size = Size(80, 30)
self.Controls.Add(self.btnTest)
self.btnTest.Click += self.Add_Control_Limits_Form_Click
def Add_Control_Limits_Form_Click(self, sender, args):
Application.Run(MySecondForm())
class MySecondForm(Form):
def __init__(self2):
self2.StartPosition = FormStartPosition.CenterScreen
self2.AutoScaleMode = AutoScaleMode.Font
self2.ClientSize = Size(800, 450)
self2.Text = "Form2"
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(MyForm())
Which, when I run it, it gives me this error message:
InvalidOperationException : Starting a second message loop on a single thread is not a valid operation. Use Form.ShowDialog instead.
I don't think it's as simple as just putting MySecondForm.ShowDialog() since I have this as a class. What am I missing?
I figured it out.
So, within the button click event, add these lines of code:
self.TopLevel = False
YF = YourForm()
YF.ShowDialog()
self.TopLevel = True
...if you want it modal. I did.
You don't need the Application.Run(MySecondForm()) code within the button click event.
Then, within your second form class, just initialize your form the way you want.

Double callback with option button

When I change between 2 options, it always returns double result (tex,tex/sculpt,sculpt). It was happening it my past projects too but I never got it solved. Restarting maya didn't work, even with rewritten code it kept happening. Any suggestions?
import maya.cmds as cmds
class UI(object):
def __init__(self):
a=cmds.window()
cmds.showWindow(a)
cmds.columnLayout()
self.displaceOptions = cmds.radioButtonGrp(la2=['Texture', 'Sculpting'], nrb=2, en=True, cc=self.check)
def check(self, *args):
option = cmds.radioButtonGrp(self.displaceOptions, q=True, sl=True)
if option == 1:
self.dispTexture()
elif option == 2:
self.dispSculpt()
def dispTexture(*args):
print('tex')
def dispSculpt(*args):
print('sculpt')
UI()
The reason is that the changeCommand reacts to the state change which is changed twice, first one radiobutton is deactivated, then another is activated. The very first call of the UI() has no radio button selected, if you select one, the callback is called only once because the state only changes once.
You could use onCommand, or offCommand which should behave a bit more as you expect.

ProgressBar in PyQt5 for multiprocessing

I have implemented a progress bar in my pythonGUI script and when the run button is clicked it executes another python script in which I have used multiprocessing for fetching query from database and genrating a output excel. Suppose there is about 10 query to execute and generate 10 excel outputs . In this case, how do I implement progress bar for multiprocessing.?
Thanks you in advance
Given that I had none of your code to go off of, I made a few assumptions about what you are using and the overall structure. Hopefully however, there is enough info here so that you can adapt this to your needs and your specific code.
import PyQt5
from PyQt5 import QtWidgets
import threading
class MyClass(object):
progressbar_progress = PyQt5.QtCore.pyqtSignal(int)
def __init__(self):
# progressBar refers to YOUR progress bar object in your interface
# Change that name to whatever you've named your actual progress bar
self.progressbar_progress.connect(self.progressbar.setValue)
#staticmethod
def start_thread(functionName, *args, **kwargs):
if len(args) == 0:
t = threading.Thread(target=functionName)
else:
try:
t = threading.Thread(target=functionName, args=args, kwargs=kwargs)
except:
try:
if args is None:
t = threading.Thread(target=functionName, kwargs=kwargs)
except:
t = threading.Thread(target=functionName)
t.daemon = True
t.start()
def button_run_clicked(self):
MyClass.start_thread(self.run_query)
# You would probably want to come up with a way to get a numerical value for your
# processes in your query. For example, if you know that you have to search through
# 10,000 entries, then that becomes your reference point. So the first query would
# be 1 out of 10,000, which would be .01% progress and the PyQt5 progress bar's
# display value is based on a percentage. So just send the current state's progress
# percentage to the signal that was created.
def run_query(self):
# All your querying code
# For example, let's assume my_query is a list
for i, q in enumerate(my_query):
# Send the value to display to the signal like this
self.progressBar.progress.emit(i / len(my_query))
print('Done!')

Python tkinter Progressbar for svn update

I need a progressbar to show the user the progress of the svn updates, but I do not know how to do this simultaneously to the svn update, I can only do it afterwards and then only indirectly, but if I let the progressbar show after the update , then I need twice the time and that's not the point.
Please help me how to update the progressbar while the update is running which needs a variable time and please give me an example of what you mean
class test():
def __init__(self, dictionary_with_paths):
self.dictionary_with_paths = {}
self.progressbar = Progressbar(range_end)
def update_local_tag_folder(self):
os.system('svn update '+ self.dictionary_with_paths['local_tags'])
def update_progressbar(self, current_value):
"""
Progressbar() is a class that simply create an tk() frame with 1
label, an progressbar and a button and it need an start value and
an end point, the end point comes with an parameter in the class,
the start/current count are given from method
Progressbar().set_current_Value(current_value)
"""
self.progressbar.set_current_value(current_Value)
self.progressbar.update()
def get_update_progress_and_update_bar(self):
"""
here is the point i have no idea how can i can get an list of
files or any other useful things
"""
SVN_list = os.system('svn ls -v -R '+ \
self.dictionary_with_paths['repository_trunk'])
"""
Console shows an list with all files, but i cant read the lines to
count that
"""
I also thought about using subprocessor but I do not know exactly how to read the output of SVN_list so that I can count the lines
SOLVED:
Fixed problem, I have created new threads in which I can once run the svn update and in another I can simultaneously create the Progressbar and let it run ...
short snapshot what i mean...
from threading import Thread
from time import sleep
class Yeeeehaaa():
def mymethod1(self, arg):
for e in range(0,arg):
print('Yeeeee')
sleep(1)
def mymethod2(self, arg):
for e in range(0,arg):
print('haaaaa')
sleep(1)
def start_threads(self):
thread = Thread(target=mymethod1, args=(10,))
thread.start()
thread = Thread(target=mymethod2, args=(10,))
thread.start()
thread.join()
thread.join()

Python multiprocessing asynchronous callback

I'm writing a program with a GUI using TKinter, in which the user can click a button and a new process is started to perform work using multiprocess.Process. This is necessary so the GUI can still be used while the work is being done, which can take several seconds.
The GUI also has a text box where the status of the program is displayed when things happen. This is often straight forward, with each function calling an add_text() function which just prints text in the text box. However, when add_text() is called in the separate process, the text does not end up in the text box.
I've thought about using a Pipe or Queue, but that would require using some sort of loop to check if anything has been returned from the process and that would also cause the main (GUI) process to be unusable. Is there some way to call a function in one process that will do work in another?
Here's an simple example of what I'm trying to do
import time
import multiprocessing as mp
import tkinter as tk
textbox = tk.Text()
def add_text(text):
# Insert text into textbox
textbox.insert(tk.END, text)
def worker():
x = 0
while x < 10:
add_text('Sleeping for {0} seconds'.format(x)
x += 1
time.sleep(1)
proc = mp.Process(target=worker)
# Usually happens on a button click
proc.start()
# GUI should still be usable here
The asyncronous things actually require loop.
You could attach function to the TkInter's loop by using Tk.after() method.
import Tkinter as tk
class App():
def __init__(self):
self.root = tk.Tk()
self.check_processes()
self.root.mainloop()
def check_processes(self):
if process_finished:
do_something()
else:
do_something_else()
self.after(1000, check_processes)
app=App()
I ended up using a multiprocessing.Pipe by using TKinter's after() method to perform the looping. It loops on an interval and checks the pipe to see if there's any messages from the thread, and if so it inserts them into the text box.
import tkinter
import multiprocessing
def do_something(child_conn):
while True:
child_conn.send('Status text\n')
class Window:
def __init__(self):
self.root = tkinter.Tk()
self.textbox = tkinter.Text()
self.parent_conn, child_conn = multiprocessing.Pipe()
self.process = multiprocessing.Process(target=do_something, args=(child_conn,))
def start(self):
self.get_status_updates()
self.process.start()
self.root.mainloop()
def get_status_updates()
status = self.check_pipe()
if status:
self.textbox.add_text(status)
self.root.after(500, self.get_status_updates) # loop every 500ms
def check_pipe():
if self.parent_conn.poll():
status = self.parent_conn.recv()
return status
return None

Categories

Resources