I created a dialog in blender 2.80 to be able to insert some values and send them through the "Ok" button.
Inside the "execute" function some operations are performed and, at the end, the window is closed. However, in case of exceptions, the problem must be handled by notifying the user and leaving the dialog box open. To do this I use a try-catch block but it does not work: in case of exception the dialog box closes whatever the returned value.
Is there any way to fix this?
#subscribe
class Test(Operator):
bl_idname = "bl_idname"
bl_label = "bl_label"
bl_description = "bl_description"
input_a = bpy.props.StringProperty(
name = "name_a",
default = "default"
)
input_b = bpy.props.StringProperty(
name = "name_b",
default = "default"
)
input_c = bpy.props.StringProperty(
name = "name_c",
default = "default"
)
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self, width = 450)
def draw(self, context):
col = self.layout.column(align = True)
col.prop(self, "input_a")
col = self.layout.column(align = True)
col.prop(self, "input_b")
col = self.layout.column(align = True)
col.prop(self, "input_c")
def execute(self, context):
try:
#something...
return {"FINISHED"}
except Exception as e:
print(str(e))
return {"CANCELLED"} #I also tried RUNNING_MODAL or PASS_THROUGH
Related
I am writing a program that should display some data that's going over a CanBus (data is being refreshed every 200ms), however when I make an objects from my class like this:
batteryDegree = PlaceInfo(root,img='battery.png',fotox=0.23,fotoy=0.35,foto_y_resize=180,foto_x_resize=180,anchor='center', text="100*C",textx=0.23,texty=0.38,canid=0x1000400,byte=2,size=30)
motorDegree = PlaceInfo(root,img='motor.png',fotox=0.75,fotoy=0.35,foto_y_resize=200,foto_x_resize=200,anchor='center', text="100*C",textx=0.76,texty=0.37,canid=0x1000400,byte=0,size=30)
Here is my class:
bus = can.interface.Bus(channel='can0')
root = Tk()
root.geometry("800x480")
root.config(bg='red')
canvas = Canvas(root,width=800,height=480,highlightthickness=0)
canvas.pack()
class PlaceInfo():
def __init__(self,root, **kwargs):
self.root = root
if 'img' in kwargs:
if 'foto_x_resize' in kwargs and 'foto_y_resize' in kwargs:
self.png = ImageTk.PhotoImage(Image.open('imgs/' + kwargs['img']).resize((kwargs['foto_x_resize'],kwargs['foto_y_resize']),Image.ANTIALIAS))
else:
self.png = ImageTk.PhotoImage(Image.open('imgs/' + kwargs['img']))
self.image = canvas.create_image(800 * kwargs['fotox'],480 * kwargs['fotoy'] ,image=self.png,anchor='center')
if 'text' in kwargs:
self.text = canvas.create_text(kwargs['textx'] * 800,
kwargs['texty'] * 480,
text=kwargs['text'],
fil=kwargs['kleur'] if 'kleur' in kwargs else 'white',
font=('arial',kwargs['size'] if 'size' in kwargs else 10))
if 'canid' in kwargs and 'index' not in kwargs:
self.changeData(kwargs['canid'], kwargs['byte'],kwargs['textx'], kwargs['texty'],kwargs['size'])
elif 'canid' in kwargs and 'index' in kwargs:
self.changeDataWithIndex(kwargs['canid'], kwargs['byte'],kwargs['textx'], kwargs['texty'],kwargs['size'],kwargs['index'])
def changeData(self,canid,byte,textx,texty,size):
try:
msg = bus.recv(1)
canvas.delete(self.text)
if msg.arbitration_id == canid:
self.data = msg.data[byte]
self.text = canvas.create_text(textx * 800,
texty * 480,
text=str(self.data),
fill='white',
font=('arial',size))
except Exception as e:
print(e)
self.root.after(250,lambda: self.changeData(canid,byte,textx,texty,size))
The program works for a few seconds but breaks after, what I mean is that it just stops displaying data and when I move my window around the colors are all over the place.
(When I print something in my functions it still prints)
Since you have more than one instance of PlaceInfo, therefore there is more than one after task reading the CanBus which may cause race condition. Also after task A may read the message for task B and vice versa.
You need to centralize the reading of the CanBus and perform the reading in a thread because recv() is a blocking task.
So you can create a CanReader class which extends from threading.Thread and call recv() in its run() function:
from threading import Thread
from queue import SimpleQueue
class CanReader(Thread):
def __init__(self, channel):
super().__init__(daemon=True)
self._bus = can.interface.Bus(channel=channel)
self._queues = {}
def register(self, canid):
if canid not in self._queues:
self._queues[canid] = []
queue = SimpleQueue()
self._queues[canid].append(queue)
return queue
def run(self):
while True:
msg = self._bus.recv()
for q in self._queues[msg.arbitration_id]:
q.put(msg)
Then you can create an instance of CanReader as below:
bus = CanReader('can0')
bus.start()
CanReader provides a function register() for PlaceInfo to register and get a SimpleQueue object holding the messages received by CanReader.
Below is modified PlaceInfo:
class PlaceInfo():
def __init__(self, root, **kwargs):
self.root = root
img = kwargs.get('img', None)
if img:
image = Image.open('images/'+img)
foto_x_resize, foto_y_resize = kwargs.get('foto_x_resize'), kwargs.get('foto_y_resize')
if foto_x_resize and foto_y_resize:
image = image.resize((foto_x_resize, foto_y_resize), Image.ANTIALIAS)
self.png = ImageTk.PhotoImage(image)
self.image = canvas.create_image(800*kwargs['fotox'], 480*kwargs['fotoy'], image=self.png, anchor='center')
textx = kwargs.get('textx', None)
texty = kwargs.get('texty', None)
fill = kwargs.get('kleur', 'white')
size = kwargs.get('size', 10)
text = kwargs.get('text', None)
if text:
self.text = canvas.create_text(textx*800, texty*480, text=text, fill=fill, font=('arial',size))
canid = kwargs.get('canid', None)
if canid:
self.queue = bus.register(canid) # register to CanReader using canid
if 'index' not in kwargs:
self.changeData(canid, kwargs['byte'])
else:
self.changeDataWithIndex(canid, kwargs['byte'], kwargs['index'])
def changeData(self, canid, byte):
try:
msg = self.queue.get_nowait() # read message
self.data = msg.data[byte]
canvas.itemconfigure(self.text, text=str(self.data))
except Exception as e:
print(e)
self.root.after(250, self.changeData, canid, byte)
Hope this help you solve the issue.
I want to pass some values to a def but am having issues with properly adding this.
In
class MyAddin():
def __init__(self, imapinfopro, thisApplication): #also tried including _self.Table_Path in this.
try:
self._pro = imapinfopro
self._thisApplication = thisApplication
self._tab = None
#self._table_path =(r'D:\junk\28355.tab')
# Some standard variables to allow functions to be created for each action for easier use. r_ is for Ribbon actions
r_item_name="Infrastructure_Data" #Name of button on main ribbon (no spaces allowed)
r_button_name="Water" #same as operations in the ribbon_customization.py
r_subroup_name="Not Abandoned" #same as "Table" and "CallBack" in the ribbon_customization.py
r_subgroup_action="Open\nClose" #same as 'MB Handler\nNo Parameter'in the ribbon_customization.py
tab = self._pro.Ribbon.Tabs.Add(r_item_name)
self._tab = tab
if tab:
group = tab.Groups.Add(r_button_name, r_button_name)
if group:
button = group.Controls.Add("ButtonOpenTable", r_subroup_name, ControlType.Button)
button.IsLarge = True
button.LargeIcon = CommonUtil.path_to_uri("pack://application:,,,/MapInfo.StyleResources;component/Images/Mapping/infoTool_32x32.png")
button.SmallIcon = CommonUtil.path_to_uri("pack://application:,,,/MapInfo.StyleResources;component/Images/Mapping/infoTool_16x16.png")
button.Command = AddinUtil.create_command(self.open_table_click)
except Exception as e:
print("Failed to load: {}".format(e))
def open_table_click(self, sender):
#table_path=(r'D:\junk\28355.tab') #if left in this is used to open the table but I want to get this value from button.Command above.
table = self._pro.Catalog.OpenTable(table_path)
CommonUtil.do("map from {}".format(table.Alias))
CommonUtil.do("browse * from {}".format(table.Alias))
pass
I want to send the value for table_path in to def open_table_click from button.Command = AddinUtil.create_command(self.open_table_click). If it wasn't a self call it would be ..._command(self.open_table_click, tablepath) and def open_table_click(self, sender, table_path):
I am wondering how to get my code to work. I have a class wich creates a popup window with buttons. Each button should be bound to subclass. But it doesnt work. What´s wrong with my code?
class chooser:
def __init__(self):
None
def show(self,title,options=["NOTHING"],size=(.5,.5)):
self.bts = {}
self.response = False
self.content = FloatLayout()
self.content.pos_hint = {"y":0,"x":0}
# create buttons
pos_cntr = 0
for opt in options:
self.bts[pos_cntr] = Button(text=opt)
self.bts[pos_cntr].size_hint = 1,float(1)/float(len(options))
self.bts[pos_cntr].pos_hint = {"x":0,"y":pos_cntr}
self.bts[pos_cntr].bind(on_press=self.canceldia)
self.content.add_widget(self.bts[pos_cntr])
print "bound"
pos_cntr += float(1)/float(len(options))
self.pop = Popup(title=title,content=self.content,auto_dismiss=False)
self.pop.size_hint = size
self.pop.open()
def canceldia(self,instance):
print "closing"
self.response = instance.text
self.pop.dismiss()
def getresponse(self):
return self.response
I have imported all needed modules.
I execute it so:
c = chooser()
c.show("hello","world",["welcome","close","nothing","example"])
I have create a root widget. The popup works fine and all is created nice but the buttons are not bound. Please help me!
In your loop, you always reference self.bts[pos_cntr], so you override it in every iteration. How about this?
for idx, opt in enumerate(options):
self.bts[idx] = Button(text=opt)
self.bts[idx].size_hint = 1,float(1)/float(len(options))
self.bts[idx].pos_hint = {"x":0,"y":pos_cntr}
self.bts[idx].bind(on_press=self.canceldia)
self.content.add_widget(self.bts[idx])
In my project i noticed that the main dialog freezes when it is setting the model of some ProxyModel, so i decided to create a new thread for this task to provide the responsiveness of the window, but right now it keeps popping an error that say:
TypeError: QTableView.setModel(QAbstractItemModel): argument 1 has unexpected type 'tuple'
and i don't know why...
Here's my code:
This is the QThread for updating the proxyModel with the arguments i provide
class ThreadedProxyModel(QThread):
def __init__(self, contacts, contactsProxyModel, groups, groupsProxyModel,
chatSession, chatSessionProxyModel, msgs, msgsProxyModel):
QThread.__init__(self)
self.contacts = contacts
self.contactsProxyModel = contactsProxyModel
self.groups = groups
self.groupsProxyModel = groupsProxyModel
self.chatSession = chatSession
self.chatSessionProxyModel = chatSessionProxyModel
self.msgs = msgs
self.msgsProxyModel = msgsProxyModel
def run(self):
self.contactsProxyModel.setSourceModel(recordsTableModel(self.contacts))
self.contactsProxyModel.setFilterKeyColumn(-1)
self.contactsProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
self.groupsProxyModel.setSourceModel(recordsTableModel(self.groups))
self.groupsProxyModel.setFilterKeyColumn(-1)
self.groupsProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
self.chatSessionProxyModel.setSourceModel(recordsTableModel(self.chatSession))
self.chatSessionProxyModel.setFilterKeyColumn(-1)
self.chatSessionProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
self.msgsProxyModel.setSourceModel(recordsTableModel(self.msgs))
self.msgsProxyModel.setFilterKeyColumn(-1)
self.msgsProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
def getContactsProxyModel(self):
return self.contactsProxyModel,
def getGroupsProxyModel(self):
return self.groupsProxyModel
def getChatSessionProxyModel(self):
return self.chatSessionProxyModel
def getMsgsProxyModel(self):
return self.msgsProxyModel
And this is the method calling the setProxyModel thread in the dialog class. Notice that all the data (contacts, groups, chatsession...) is fine:
def setProxyModel(self):
progress = QProgressDialog("Initializing UI ...", "Abort", 0, 0, self)
progress.setWindowTitle("WhatsApp Browser ...")
progress.setWindowModality(Qt.WindowModal)
progress.setMinimumDuration(0)
progress.setCancelButton(None)
progress.show()
queryTh = ThreadedProxyModel(self.contacts, self.contactsProxyModel, self.groups, self.groupsProxyModel,
self.chatSession, self.chatSessionProxyModel, self.msgs, self.msgsProxyModel,)
queryTh.start()
while queryTh.isRunning():
QApplication.processEvents()
self.contactsProxyModel = queryTh.getContactsProxyModel()
self.groupsProxyModel = queryTh.getGroupsProxyModel()
self.chatSessionProxyModel = queryTh.getChatSessionProxyModel()
self.msgsProxyModel = queryTh.getMsgsProxyModel()
progress.close()
And this is in the init method in my dialog, i create the proxymodels and call the method for updating them in the Thread and then i set them up in various QTableView:
self.contactsProxyModel = QSortFilterProxyModel(self)
self.groupsProxyModel = QSortFilterProxyModel(self)
self.groupMembersProxyModel = QSortFilterProxyModel(self)
self.chatSessionProxyModel = QSortFilterProxyModel(self)
self.chatMsgsProxyModel = QSortFilterProxyModel(self)
self.msgsProxyModel = QSortFilterProxyModel(self)
self.setProxyModel()
self.contactsTableView.setModel(self.contactsProxyModel)
self.contactsTableView.resizeColumnsToContents()
self.groupsTableView.setModel(self.groupsProxyModel)
self.groupsTableView.resizeColumnsToContents()
self.chatSessionTableView.setModel(self.chatSessionProxyModel)
self.chatSessionTableView.resizeColumnsToContents()
self.chatSessionTableView.clicked.connect(self.setChatMsgsProxyModel)
self.chatMsgsTableView.resizeColumnsToContents()
self.groupsTableView.clicked.connect(self.setGroupMembersProxyModel)
self.groupMembersTableView.resizeColumnsToContents()
self.msgsTableView.setModel(self.msgsProxyModel)
self.msgsTableView.resizeColumnsToContents()
Thank you for any advice, i'm pretty stuck...
Not sure, but it seems that
def getContactsProxyModel(self):
return self.contactsProxyModel,
return a tuple, try to delete the comma
I have been unable to get drag and drop validation working in pygtk. I am out of ideas and would like a second opinion.
My goal is to only allow files which contain .jpg to be dropped.
Specifically, whenever I call widget.drag_get_data within the drag-motion callback The X11 cursor locks up. Making debugging tedious and aggravating since I have to kill X11 and re launch everything.
Here is my source code, I think the issue lies specifically in the drag_motion_cb and drag_data_received_cb methods. I have left the commented out sections I have tried before.
Using Google code search searching for drag_get_data doesn't show anyone else doing advanced validation. So I'm guessing others failed as well.
I am out of ideas and will end up just using simple DnD in my linux port (without proper validation) if I cannot figure this out.
Thanks in advance.
import pygtk
pygtk.require('2.0')
import gobject
import gtk
TARGET_TEXT_URI_LIST = 0
drop_targets = [
("text/uri-list", 0, TARGET_TEXT_URI_LIST)
]
class TestApp(gobject.GObject):
builder = gtk.Builder()
window = None
button = None
def init(self):
gobject.GObject.init(self)
assert self.builder != None
self.builder.add_from_file("MainWindow.glade");
self.window = self.builder.get_object("window1")
self.button = self.builder.get_object("button1")
self.window.connect("destroy", gtk.main_quit)
self.button.drag_dest_set(gtk.DEST_DEFAULT_ALL, drop_targets, gtk.gdk.ACTION_COPY|gtk.gdk.ACTION_LINK|gtk.gdk.ACTION_MOVE)
self.button.connect("drag-data-received", self.drag_data_received_cb)
self.button.connect("drag-drop", self.drag_drop_cb)
self.button.connect("drag-motion", self.drag_motion_cb)
self.button.connect("drag-leave", self.drag_leave_cb)
self.window.show_all()
drop_data_ready = False
drop_occurred = False
drop_highlight = False
drop_data = None
def drag_data_received_cb(self,widget,context,x,y,data,info,timestamp):
print "drag_data_received_cb"
# Check to see if we have the drop data yet.
if False == self.drop_data_ready:
# If this is data we expected or can handle, then process it.
if TARGET_TEXT_URI_LIST == info and data.get_format() == 8 and data.get_length() > 0:
self.drop_data = data.get_uris()
self.drop_data_ready = True
context.drag_status(gtk.gdk.ACTION_COPY, timestamp)
# Actual drop handling code.
if True == self.drop_occurred:
# Reset state.
self.drop_occurred = False
print "RECEIVED DROP",self.drop_data
# Notify whether we handled the drop or not.
context.finish(True,False,timestamp)
# Clean up.
self.drag_leave_cb(widget, context, timestamp)
return True
def drag_drop_cb(self,widget,context,x,y,timestamp):
target = widget.drag_dest_find_target(context, widget.drag_dest_get_target_list())
# Is it something we can handle?
if target == gtk.gdk.atom_intern("text/uri-list", False):
# Tell data recieved handler (do_drag_data_received) we can actually handle the drop.
self.drop_occurred = True
widget.drag_get_data(context,target,timestamp)
# We can handle this data type.
return True
else:
# We cannot handle the drop.
return False
pass
def drag_motion_cb(self,widget,context,x,y,timestamp):
if not self.drop_data_ready:
widget.drag_get_data(context, gtk.gdk.atom_intern("text/uri-list",False), timestamp)
return False
"""
target = widget.drag_dest_find_target(context, widget.drag_dest_get_target_list())
if target == gtk.gdk.atom_intern("text/uri-list", False):
if True == self.drop_data_ready:
pass
else:
#widget.drag_get_data(context, target, timestamp)
pass
"""
context.drag_status(gtk.gdk.ACTION_COPY, timestamp)
"""
if target == gtk.gdk.atom_intern("text/uri-list", False):
if True == self.drop_data_ready:
if repr(drop_data).find(".jpg") != -1:
# Tell Gdk we can handle this.
context.drag_status(gtk.gdk.ACTION_COPY, timestamp)
# Draw drop highlight (but only once).
if False == self.drop_highlight:
widget.drag_highlight()
self.drop_highlight = True
# Return here, don't fall through.
return True
else:
# Request drag data from the source.
widget.drag_get_data(context, target, timestamp)
# Fall-through to not allowing.
"""
# not something we can handle
#context.drag_status(0, timestamp) # Don't allow drop.
return True
pass
def drag_leave_cb(self,widget,context,timestamp):
# Cleanup drag data.
if True == self.drop_data_ready:
self.drop_data = None
self.drop_data_ready = False
# Un-draw the highlight.
if True == self.drop_highlight:
widget.drag_unhighlight()
self.drop_highlight = False
pass
gobject.type_register(TestApp)
def main():
car = TestApp()
gtk.main()
if name == 'main':
main()
I think you must do something like this in drag_data_received_cb
def drag_data_received_cb(self, obj, context, x, y, selection, target_id, etime):
try:
dtype = selection.get_data_type()
except AttributeError:## Old PyGTK
dtype = selection.type
if dtype=='image/jpeg':
image_data = selection.data
## do somthing with image_data
return True
return False