A am trying to add a scroll bar that scrolls downwards but it doesn't work. though it works when i do xview so I'm not sure why its not working for yview.
sry for bad grammar.
round_desc_scroll=tk.Scrollbar(root,orient='vertical',command=round_desc_label.yview)
round_desc_scroll.pack(side=tk.RIGHT,fill=tk.Y)
Traceback (most recent call last):
File "/Volumes/AMIN ALI/zorc save after scroll.py", line 134, in <module>
round_desc_scroll=tk.Scrollbar(root, orient='vertical',command=round_desc_label.yview)
AttributeError: 'Entry' object has no attribute 'yview'
Like the error says, an Entry widget does not have a yview method. This is because the Entry widget can only ever display a single line of text. It has an xview method to scroll in the horizontal direction because the data can be longer than the widget.
If you need to display or allow the user to input multiline data, you need to use a Text widget which supports scrolling in both directions.
Related
Im creating an application with PyQt5. I wanted to create a widget that lives inside a frame and that the user can move and resize at will. Following this answer i came to the conclusion that i could use QDockWidgets to do this.
Thing is: i want my QDockWidget to only exist and be movable inside a frame of my mainwindow. It seems that setAllowedAreas() could do this restriction for me but it can only be used with QtDockWidgetAreas, and preexisting areas are just default areas of the main window.
So currently my code is like this:
#!/usr/local/bin/pydm
from PyQt5.QtWidgets import QDockWidget
from pydm import Display
class Window(Display): ##Main window class.
def __init__(self, args, macros):
super(Window, self).__init__(None, args, macros,
ui_filename="main.ui")
self.pushButton.clicked.connect(self.createDock)
def createDock(self):
self.dock=QDockWidget()
self.dock.raise_()
self.dock.show()
(pydm is amodule that inherits all classes from PyQt and allows all default functionalities to work just fine.)
The main.ui file created with QtDesigner is just a widget window with a frame and a pushbutton. The generated window is in the image below:
So obviously my DockWidget can go outside the frame. I tried self.dock.setAllowedAreas(self.myFrame) but i got the expected error when clicking the button:
Traceback (most recent call last):
File "./main.py", line 16, in createDock
self.dock.setAllowedAreas(self.frame)
TypeError: setAllowedAreas(self, Union[Qt.DockWidgetAreas, Qt.DockWidgetArea]): argument 1 has unexpected type 'QFrame'
i also tried:
from PyQt5.QtCore import Qt
and in the createDock(self) function:
myArea = Qt.DockWidgetArea(self.frame)
self.dock.setAllowedAreas(myArea)
But i got:
Traceback (most recent call last):
File "./main.py", line 17, in createDock
myArea = Qt.DockWidgetArea(self.frame)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'QFrame'
Looking at the QDockWidgetArea it doesnt look that i can make a custom Area at all. At least not that i could find.
Is there any way at all to achieve the functionality that i want?
I have a tk.Entry widget, that I need to have focus_set() on, and also need the function grid(). Here's the piece of code:
e = Entry(...).focus_set()
e.grid(columnspan=3)
But the interpreter gives this problem:
Traceback (most recent call last):
File "D:\...\main.py", line 10, in <module>
e.grid(columnspan=3)
AttributeError: 'NoneType' object has no attribute 'grid'
Also, if I try to put all the functions in one line it gives same error for the function that goes after first (error for grid() if Entry(...).focus_set().grid(...) and same in reverse). What do I do?
focus_set() does not return the Entry itself, but None, so you simply said can't chain the calls like that.
Instead, just call them separately.
e = Entry(...)
e.focus_set()
e.grid(columnspan=3)
I would like to create a GUI that receives two paths (a directory full of .txt documents and the destination of a new .csv file created from the files of the previously mentioned folder).
I am having trouble calling the function munge():
action = tk.Button(win, text="To .csv",command=munge(input_directory,output_directory))
Nevertheless, this exception raised:
/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/user/PycharmProjects/script.py
Traceback (most recent call last):
File "/Users/user/PycharmProjects/script.py", line 82, in <module>
action = tk.Button(win, text="To .csv", command=munge(input_directory,output_directory))
File "/Users/user/PycharmProjects/script.py", line 39, in munge
test = tuple(retrive(directory))
File "/Users/user/PycharmProjects/script.py", line 31, in retrive
for filename in sorted(glob.glob(os.path.join(directory_path, '*.txt'))):
File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py", line 70, in join
elif path == '' or path.endswith('/'):
AttributeError: StringVar instance has no attribute 'endswith'
Process finished with exit code 1
How can I correctly call the aforementioned function with the help of the Button widget?. I tried to set the name of the variable as indicated here question, but it did not worked.
update
Then from an answer of this question, I tried the following:
action = tk.Button(win, text="To .csv", command=lambda:munge(input_directory,output_directory))
Based on the error message, you seem to be trying to call the endswith method of a StringVar object. If you look at the documentation for such an object you'll see there's no such method. That is why you get the error that you do.
Assuming that path is an instance of a StringVar, you must call the get method in order to have the string stored by the object:
path_string = path.get()
if path_string == "" or path_string.endswith('/'):
...
You might want to consider reading a bit on callback functions in Tkinter, here is a useful link in order to do so http://effbot.org/zone/tkinter-callbacks.htm:
For simple cases like this, you can use a lambda expression as a link
between Tkinter and the callback function:
def callback(number):
print "button", number
Button(text="one", command=lambda: callback(1))
your function is being executed as soon as your Button widget loads, you want to avoid this.
After all, it worked with: action = tk.Button(win, text="To .csv", command=lambda:munge(input_directory.get(),output_directory.get())). However, from Bryan Oakley answer I belive that this is not the correct way to do this.
You want to call the .get() method on the StringVar to get the string it contains otherwise it's just the StringVar instance.
I'm still working on my little Tkinter project which is simple a logging console that prints incoming text from the serial line to a Text Widget with some coloring applied.
One question is open and can be found here: Python Tkinter Text Widget with Auto & Custom Scroll
However, even without manual scrolling (so I'm using self.text.yview(END) to auto-scroll to the bottom after inserting text with self.text.insert(END, str(parsed_line)).
The script actually works but every now and then it throws some "silent" exceptions within the Tkinter thread that does not let the whole application crash:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python26\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:\Python26\lib\lib-tk\Tkinter.py", line 2813, in set
self.tk.call((self._w, 'set') + args)
TclError: expected floating-point number but got "0.7807017543859649integer but got "end""
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python26\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:\Python26\lib\lib-tk\Tkinter.py", line 2813, in set
self.tk.call((self._w, 'set') + args)
TclError: invalid command name ".15427224integer but got "end""
It looks as if some method expected a an integer, returns the string integer but got "end" to a method that expected a float which is concatinated with the error message. The float number in that string looks like the position of the scrollbar that I have attached to my text widget:
(...)
scrollbar = Scrollbar(root)
scrollbar.pack(side=RIGHT, fill=Y)
text = Text(wrap=WORD, yscrollcommand=scrollbar.set)
scrollbar.config(command=text.yview)
text.pack(expand=YES, fill=BOTH)
(...)
I have the feeling that it happens when a lot of lines are inserted within a short time. But since I only have one thread interacting with Tkinter this cannot be a threading issue.
I also got very random errors like that before I had applied the str() function to parsed_line in self.text.insert(END, str(parsed_line)).
This is very strange behavior and I'm wondering if anyone could explain what this is about and how to fix it.
Thanks a lot!
mtTkinter allows multithreading with Tkinter, you can get it here:
http://tkinter.unpythonic.net/wiki/mtTkinter
Just import mtTkinter in place of Tkinter. This will allow you to insert text into a Text widget from multiple threads without conflict. I used it for some instant messaging software I wrote and it works wonderfully.
I am currently working on a Tkinter app, which uses as a main widget a TextWidget.
When I try to get the current selection, an error is raised, but I don't get why...
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:\Users\Lina\Documents\Programmation\VPE project.py", line 502, in rechercher
texte=code_text.selection_get()
File "C:\Python27\lib\lib-tk\Tkinter.py", line 626, in selection_get
return self.tk.call(('selection', 'get') + self._options(kw))
TclError: PRIMARY selection doesn't exist or form "STRING" not defined
Thanks.
EDIT: I know why it wasn't working, i binded to Ctrl-F, but it is already binded in the TextWidgets (by default, it does exactly the same thing as LeftArrow).
Now the problem is, how do I get rid of that?
That error is simply telling you that nothing is selected. It's not an error per se, just it's way of saying "there's nothing to get". That may be true, or you may have something selected but it isn't being exported to "the selection". If you have the exportselection option on the widget set to true, anything you select should be copied to the selection. If it's not, there's not enough code in your question to answer why.
However, to answer the question of "how do I get the text that is selected in the widget": The text that is selected in a text widget has the tag 'sel'. You can get this text with textwidget.get('sel.first', 'sel.last')
Using the get method with the tags is more correct than using selection_get since it's possible to have nothing selected in the widget yet still have selection_get return something (eg: return whatever other widget has exported to the selection)
I got the error when selecting empty space in text box. To avoid the error, I have used
checking with re.search for text in the selection.
word = text.selection_get()
if re.search(r'\w+', word):
some_action()