Insert Text into a TextBuffer via a Function - python - python

I have following problem:
How can i insert text in my textbuffer?
Interface.py
class MainWindow:
def __init__(self):
# Build our Interface from the XML/Glade file
gladefile = "MainWindow.glade"
try:
self.builder = Gtk.Builder()
self.builder.add_from_file(gladefile)
except:
print("Failed to load Glade file: %s" % gladefile)
# Connect signals
self.builder.connect_signals(self)
# Get the widgets
self.window = self.builder.get_object("MainWindow")
...
# TextViews
self.TextViewCommandInput = self.builder.get_object("TextViewCommandInput")
self.TextViewCommandOutput = self.builder.get_object("TextViewCommandOutput")
...
def DrawCommandView(output):
TextBufferCommandInput = MainWindow.TextViewCommandInput.get_buffer()
TextBufferCommandInput.insert_at_cursor(output + "\n")
And import "DrawCommandView" in a file
Commands.py
from Interface import MainWindow, DrawCommandView
output = "Hello World"
DrawCommandView(output)
if __name__ == "__main__":
StartMainWindow = MainWindow()
StartMainWindow.main()
But I keep getting this error:
Traceback (most recent call last):
File "/home/user/Dokumente/Workspace/project/Commands.py", line 5, in <module>
DrawACommandView(output)
File "/home/user/Dokumente/Workspace/project/Interface.py", line 182, in DrawCommandView
TextBufferCommandInput = MainWindow.TextViewCommandInput.get_buffer()
AttributeError: class MainWindow has no attribute 'self'
Thanks for your help!
greetz

When you say TextBufferCommandInput = MainWindow.TextViewCommandInput.get_buffer()
You are asking for a class attribute in MainWindow named TextViewCommandInput. You don't have a class attribute TextViewCommandInput, you have an instance attribute TextViewCommandInput. You need to pass an instance of MainWindow into DrawCommandView in order to get to TextViewCommandInput.

I believe you have to set_text() instead of get_buffer().
See the set_text() documentation.
Then later get_buffer() can retrieve the text inserted by set_text().
Here are some methods I've been using to have a generic way to use the buffer.
def GetTextBuffer(self):
self.text_buffer = self.text_edit.get_buffer()
# self.text_edit is a Gtk.TextView() instance
# to get the text buffer from TextView
# buffer.get_text( start iterator, end iterator, bool )
# the third argument set to True = Include hidden characters
# third argument set to False = Don't include hidden characters
# hidden characters would be visual formatting markup and such
return self.text_buffer.get_text(
self.text_buffer.get_start_iter(),
self.text_buffer.get_end_iter(),
False)
def SetTextBuffer(self, to_buffer):
# to_buffer is user input from widgets, or default values set at run time.
text_buffer = self.text_edit.get_buffer()
text_buffer.set_text(to_buffer)

Related

python3 with tkinter: call widget from a function

I'm having a problem with this code:
from tkinter import *
class app:
def create(arrSettings):
proot = Toplevel()
proot.title("Settings")
m = Frame(proot).pack() #Some Frames so I can arrange them how I'd like to
mcan = Canvas(proot)
mcan.pack(fill="both", side="left")
x = Frame(proot).pack()
xcan = Canvas(proot)
xcan.pack(fill="both", expand="yes", side="left")
win_0 = Frame(xcan)
lbl_0 = Label(win_0, text="Option0").pack()
txt_0 = Text(win_0).pack()
win_0.pack()
win_1 = Frame(xcan)
lbl_1 = Label(win_1, text="Option1").pack()
txt_1 = Text(win_1).pack()
win_1.pack()
btn_menu0 = Button(mcan, text="Menu0", command=app.func_btn_menu0).pack()
btn_menu1 = Button(mcan, text="Menu1", command=app.func_btn_menu1).pack()
def func_btn_menu0():
lbl_0.config(text="foo") # <-- Problem
txt_0.insert("end", "bar") # <-- Problem
def func_btn_menu1():
pass
(I left the code for the design(bg, border, ...) out)
This is another window which will be started by the main one.
It shows some buttons on the left and some labels and textboxes on the right.
Whenever a button on the left has been pushed the text of the labels should be changed.
That's the problem: When I push a button I get this error and the text won't be changed:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.4/tkinter/__init__.py", line 1536, in __call__
return self.func(*args)
File "/[...]/program.py", line 27, in colormain
lbl_0.config(text="Background")
NameError: name 'lbl_0' is not defined
I don't really understand why this gives me an error so I'd like to ask you.
This code is being started from the main window with the code:
program.app.create(arrSettings) #arrSettings is an array in which some colors for the design are
Thanks in advance.
Do not declare and pack in the same line
Return of this peice of code is None
Label(win_0, text="Option0").pack()
whereas, this returns an object of Label class
Label(win_0, text="Option0")
so use:-
lbl_0 = Label(win_0, text="Option0")
lbl_0.pack()
instead of
lbl_0 = Label(win_0, text="Option0").pack()
Also use self object as argument to functions. Check that the variables are in scope wherever you are using it.
This should help you get through this error...

Python AttributeError : Object has no attribute in QGIS Plugin

I'm trying to create a GUI with QT Designer. I've converted my .ui designer file to a .py.
Here is my code:
from PyQt4.QtCore import QSettings, QTranslator, qVersion, QCoreApplication
from PyQt4.QtGui import QAction, QIcon
from qgis.core import *
import resources
from delete_feature_dialog import DeleteFeatureDialog
import os.path
class DeleteFeature:
def __init__(self, iface):
# Save reference to the QGIS interface
self.iface = iface
# Declare instance attributes
self.actions = []
self.menu = self.tr(u'&DeleteFeature')
self.toolbar = self.iface.addToolBar(u'DeleteFeature')
self.toolbar.setObjectName(u'DeleteFeature')
def add_action(
self,
icon_path,
text,
callback,
enabled_flag=True,
add_to_menu=True,
add_to_toolbar=True,
status_tip=None,
whats_this=None,
parent=None):
# Create the dialog (after translation) and keep reference
self.dlg = DeleteFeatureDialog()
....
return action
def initGui(self):
icon_path = ':/plugins/DeleteFeature/icon.png'
self.add_action(
icon_path,
text=self.tr(u''),
callback=self.run,
parent=self.iface.mainWindow())
def run(self):
#this code will populate the combo box with all vector layer
self.dlg.layerListCombo.clear()
layers = self.iface.legendInterface().layers()
layer_list = []
for layer in layers:
layerType = layer.type()
if layerType == QgsMapLayer.VectorLayer:
layer_list.append(layer.name())
self.dlg.layerListCombo.addItems(layer_list)
# show the dialog
self.dlg.show()
# Run the dialog event loop
result = self.dlg.exec_()
# See if OK was pressed
if result:
# Do something useful here - delete the line containing pass and
# substitute with your code.
selectedLayerIndex = self.dlg.layerlistcombo.currentIndex()
selectedLayer = layers [selectedLayerIndex]
.....
Then when I open the plugin, I get the following error:
'DeleteFeatureDialog' objectObject has no attribute
'layerlistcombo'in QGIS Plugin
Any suggestion for this.
Seems that you wrote:
selectedLayerIndex = self.dlg.layerlistcombo.currentIndex()
but you should have written:
selectedLayerIndex = self.dlg.layerListCombo.currentIndex()
Like you did previously in your code (notice the Camel Notation when writing, not just lower-case letters), which is probably causing the No Attribute error you get.

RuntimeError: deleteUI: Object 'Animation_Copy_Tool' not found

Getting this error when pressing the "Close Window" button in my UI. This button should delete the UI window but isn't. Full traceback:
Error: deleteUI: Object 'Animation_Copy_Tool' not found.
Traceback (most recent call last):
File "", line 36, in closeBtnCmd
RuntimeError: deleteUI: Object 'Animation_Copy_Tool' not found. #
# Animation Copy Tool
# Bakari Holmes 5/7/2015
# This is designed to copy and existing animation
# from one rig to another and make the process easier
# with a simple UI
import maya.cmds as mc
import functools
import maya.mel as mm
import pprint
class AnimCopyWindow(object):
##classmethod
def showUI(cls):
win = cls()
win.create()
return win
def __init__(self):
self.window = "Animation Copy Tool"
self.title = "Animation Copier"
self.size = (546,350)
def pasteTheseKeys(self, *args):
self.offsetVal = mc.intFieldGrp(self.int_offset, q=True, value1=True)
self.selObj_pasteKeys = mc.ls(sl=True)
for objectQuant in self.selObj_pasteKeys:
print objectQuant
self.ct = mc.currentTime(query = True)
self.t = self.ct + self.offsetVal
mc.currentTime(self.t)
# mc.selectKey(selObj_pasteKeys[objectQuant])
mc.pasteKey(time=(self.t,self.t), f=(1.0,1.0), option="merge", copies=1, to=0, fo=0, vo=0)
def closeBtnCmd(self,*args):
mc.deleteUI(self.window,window=True)
def create(self):
# check to see if window exists already
if mc.window(self.window,exists=True):
mc.deleteUI(self.window,window=True)
self.window = mc.window(self.window, title=self.title,widthHeight=self.size,menuBar=True)
self.copyAnim = mc.window(title="Transfer Animation Tool", backgroundColor=[0.3,0.3,0.3],sizeable=False,resizeToFitChildren=True)
#set the layout for UI
mc.columnLayout(adjustableColumn=True)
self.tx_src = mc.textFieldGrp(label="Source Object", editable=False, text=sel[0])
self.int_offset = mc.intFieldGrp(label="Frame Offset Amount", value1=0)
#add paste animation button
self.btn1 = mc.button(label="PASTE ANIMATION", command=self.pasteTheseKeys, bgc=[0.1,0.1,0.5])
#add close button window
self.btn2 = mc.button(label="CLOSE WINDOW", command=self.closeBtnCmd, bgc=[0.2,0.2,0.2])
mc.showWindow()
#################################
#####end of class definition#####
#################################
def keys_as_dictionary(channel):
"""return a dictionay of times:values for <channel>"""
keys = mc.keyframe(channel, q=True, tc=True) or []
values = mc.keyframe(channel, q=True, vc=True) or []
return dict(zip(keys, values))
def channels():
"""return a dictionary of <plug>:<channel_dict> for each animated plug selected"""
keys = mc.keyframe(sl=True, n=True, q=True)
result = {}
for k in keys:
plugs = mc.listConnections(k, p=True)[0]
result[plugs]= keys_as_dictionary(k)
return result
#store selected object info
sel = mc.ls(selection=True)
if (len(sel) != 1):
mm.eval("warning Must select one animated object;")
else:
mc.copyKey()
win = AnimCopyWindow()
win.create()
pprint.pprint(channels())
This error almost always means your UI element is not named what you think it is: Maya will automatically rename the items to make sure that no two siblings have the same name -- you can ask for "my_window" and get back "my_window123" . So you need to capture the actual name that is returned from cmds.window() or whatever ui command you use and delete that. Hard coded names are never reliable

Python: Can't pop from an empty list

I am creating a python program to detect and enable usb to usb data transfer between usb storage drives. However I am having an issue with updating the dev_label (device name of the drive) and passing it to Exchange. Here is the code :
serial_list=[]
context = Context()
monitor = Monitor.from_netlink(context)
monitor.filter_by(subsystem='block',device_type='partition')
observer = GUDevMonitorObserver(monitor)
def device_connected(observer, device):
Welcome.device_count+=1
flag =False
for iden in serial_list :
if iden == device.__getitem__('ID_SERIAL_SHORT'):
flag=True
if flag ==False:
serial_list.append(device.__getitem__('ID_SERIAL_SHORT'))
Welcome.dev_label.append(str(device.__getitem__('ID_FS_LABEL')))
size = len(Welcome.dev_label)
label = gtk.Label('Device connected :: {0!r}'.format(Welcome.dev_label[size-1]))
Welcome.vbox.pack_start(label)
Welcome.window.show_all()
if Welcome.device_count<2:
label = gtk.Label('Connect the second device')
Welcome.vbox.pack_start(label)
Welcome.window.show_all()
else :
Exchange()
observer.connect("device-added",device_connected)
monitor.start()
class Welcome:
device_count = 0
window = gtk.Window()
vbox= gtk.VBox(False, 5)
dev_label = []
def __init__(self):
self.window.set_default_size(300, 300)
self.window.set_title("Welcome")
label = gtk.Label("Connect the desired device")
self.vbox.pack_start(label)
self.window.add(self.vbox)
self.window.connect("destroy", lambda q: gtk.main_quit())
self.window.show_all()
class Exchange:
window1 = gtk.Window(Welcome.dev_label.pop())
window2 = gtk.Window(Welcome.dev_label.pop())
def __init__(self):
width = gtk.gdk.screen_get_default().get_width()
height = gtk.gdk.screen_get_default().get_height()
self.window1.resize(width/2,height)
self.window2.resize(width/2,height)
self.window2.move(self.window1.get_position()[0]+width/2, self.window1.get_position()[1])
label = gtk.Label("Hello")
self.window1.add(label)
self.window1.connect("destroy" , lambda q : gtk.main_quit())
self.window1.show_all()
label = gtk.Label("World")
self.window2.add(label)
self.window2.connect("destroy",lambda q : gtk.main_quit())
self.window2.show_all()
Welcome()
gtk.main()
The error shown in the trace back is :
Traceback (most recent call last):
File "project.py", line 70, in <module>
class Exchange:
File "project.py", line 71, in Exchange
window1 = gtk.Window(Welcome.dev_label.pop())
IndexError: pop from empty list
I can't figure out how to synchronize all these event so that the compiler doesn't throw an error. Values are being popped from Welcome.dev_label only after they've been updated in device_connected so why does the compiler have a problem? I am a python newbie so please be gentle.
This is not the compiler givin errors but the program.
You can change your class to this:
import time
class Exchange:
while not Welcome.dev_label: time.sleep(0.001)
window1 = gtk.Window(Welcome.dev_label.pop()) # line 4
while not Welcome.dev_label: time.sleep(0.001)
window2 = gtk.Window(Welcome.dev_label.pop())
This would be kind of a synchronization primitive given that only line 4 and 6 remove content.
In general you would use a queue for this.
import queue # Python3 # import Queue Python 2
Welcome.dev_label # = queue.Queue()
Welcome.dev_label.put(...) # instead of append
Welcome.dev_label.get(...) # instead of pop
But I do not know wether your code uses threads and runs in parallel. If the time.sleep example works then you can switch to a queue.

PyQt and Maya, with threading = False?

I've been investigating this problem for 3 days now, without any luck. I'm quite new to all this so maybe there is something I'm missing.
The problem applies to: Maya.cmds, PyMel and evaluated MEL using QThread or just Thread
This code is designed to run on the "mayapy" python interpreter which follows Maya. I've created a short example which re-creates the same error in multiple instances.
One button works, the other one doesn't. But they run the same code.
from PyQt4 import Qt
class doStuff( Qt.QThread ):
taskProgress = Qt.pyqtSignal(int)
# --------------------------------------------------------- #
# Here things start to crash...
def run( self ):
# This works
persp = mel.general.PyNode('persp')
print persp.translateX.get()
# This dont work
poiLights = mel.general.ls( exactType="pointLight" )
for light in poiLights:
print light
# This dont work
geo = mel.general.PyNode('pPyramidShape1')
print mel.modeling.polyEvaluate( geo, face=True )
# Emit progress
self.taskProgress.emit( 1 )
return
# END
# --------------------------------------------------------- #
class ui( Qt.QWidget ):
def __init__(self, parent=None):
super(ui, self).__init__(parent)
# Init QThread
self.thread = doStuff()
# Create Widgets
buttonNo = Qt.QPushButton("Start - Dont work")
buttonYes = Qt.QPushButton("Start - Works")
# Setup Layout
layout = Qt.QVBoxLayout()
layout.addWidget( buttonYes )
layout.addWidget( buttonNo )
self.setLayout( layout )
self.show()
# --------------------------------
# PROBLEM AREA: Button signals
# This one dont work, but starts the thread correctly.
self.connect( buttonNo, Qt.SIGNAL("clicked()"), self.thread.start )
# This one works, but dont start the thread correctly.
self.connect( buttonYes, Qt.SIGNAL("clicked()"), self.thread.run )
# --------------------------------
self.thread.taskProgress.connect( self.updateProgress )
return
# Feedback progress status
def updateProgress( self, value ):
print 'Current progress is:', value
return
if __name__ == '__main__':
import sys
app = Qt.QApplication(sys.path)
program = ui()
# init maya
import pymel.core as mel
filePath = '/Users/ecker/Dropbox/Scripts/RibExporter/mayaScene3ani.ma'
mel.openFile( filePath, f=True, o=True )
sys.exit(app.exec_())
This code creates 2 buttons which start executing the same function when pressed. One executes thread.start and thread.run.
thread.start will make the thread work as it should, being able to feed back data to the Qt interface (for a progress bar), but most of the Maya code will start to return all kinds of errors like this:
Traceback (most recent call last):
File "/Users/ecker/Dropbox/Scripts/RibExporter/error_recreation2.py", line 22, in run
poiLights = mel.general.ls( exactType="pointLight" )
File "/Applications/Autodesk/maya2012/Maya.app/Contents/Frameworks/Python.framework/Versions/Current/lib/python2.6/site-packages/pymel/core/general.py", line 969, in ls
res = _util.listForNone(cmds.ls(*args, **kwargs))
File "/Applications/Autodesk/maya2012/Maya.app/Contents/Frameworks/Python.framework/Versions/Current/lib/python2.6/site-packages/pymel/internal/pmcmds.py", line 134, in wrappedCmd
res = new_cmd(*new_args, **new_kwargs)
TypeError: Flag 'long' must be passed a boolean argument
It is a boolean argument, and no matter what arguments I try to give it in what format and ways, it will always give errors very similar to this. At the same line res = new_cmd(*new_args, **new_kwargs) needing a boolean.
I need the thread to start, not just run. Unless there is a different way to do the threading, a workaround?
Maya does not work well with threads. The key here is to use maya.utils.executeInMainThreadWithResult.
http://download.autodesk.com/us/maya/2010help/index.html?url=Python_Python_and_threading.htm,topicNumber=d0e182779
I hope this helps.

Categories