Certain Tkinter options not available when in IDLE - python-3.x

I am trying to create a button that when the widget is active in changes color (I am using python-idle3).
I tried importing tkinter as follows:
from tkinter import *
from tkinter import ttk
My button creation codes are as follows but does not work when I included the activebackground option
start_button=Button(window_frame,text="START",width=70,height=2).grid(row=8,column=0,stick="E",activebackground="black")
Error message when using activebackground:
Traceback (most recent call last): File "/root/Desktop/GUi #1.py",
line 37, in <module>
Button_expirement() File "/root/Desktop/GUi #1.py", line 26, in Button_expirement
start_button=Button(window_frame,text="START",width=70,height=2).grid(row=8,column=0,stick="E",activebackground="black")
File "/usr/lib/python3.2/tkinter/__init__.py", line 1914, in
grid_configure
+ self._options(cnf, kw))
**_tkinter.TclError: bad option "-activebackground": must be -column, -columnspan, -in, -ipadx, -ipady, -padx, -pady, -row, -rowspan, or -sticky**
I noticed that some other widget features are also limited. Any solution to this?

activebackground isn't part of the function call to grid. See http://effbot.org/tkinterbook/grid.htm
But it is in the function call to Button. See http://effbot.org/tkinterbook/button.htm
So perhaps you meant to write this?
start_button=Button(window_frame,text="START",width=70,height=2,activebackground="black").grid(row=8,column=0,stick="E")
...or if you meant to set the background to black, you can set it in the Tk variable (see
Python Tkinter how to color a window using grid).
root = Tk()
root.configure(bg='black')

Related

Python script works fine independently, however, when called from an external script, I get NameError name 'x' is not defined

So basically, I am learning Python (therefore I am new, so be gentle lol). I work in IT and wanted to make a program that has all the basic stuff that I do everyday.
The main program opens up and shows a few options for tools and such. I wanted to add a To Do List to the options.
When my To Do list is called the GUI will appear, however, whenever the buttons are clicked, I get the NameError. I assume the main program just doesn't understand the defined functions that I have assigned to the buttons on the To Do list.
I am curious as to why. Of course I would love a solution, however, I am genuinely curious and interested as to why the interpreter doesn't see or "understand" the defined functions.
I called the To Do List using
toDoBtn = tk.Button(self, text = "To Do List",
command=lambda: exec(open("ToDo.py").read()))
The error I get is
Traceback (most recent call last):
File "C:\Users\brannon.harper\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "<string>", line 49, in insertTask
NameError: name 'inputError' is not defined
I will add the beggining part of ToDo.py, however, I feel as if the issue is how I am calling the script, not how the script is written.
from tkinter import *
from tkinter import messagebox
tasks_list = []
counter = 1
# Function for checking input error when
# empty input is given in task field
def inputError() :
if enterTaskField.get() == "" :
messagebox.showerror("Input Error")
return 0
return 1
The ToDo.py script ends with
if __name__ == "__main__" :
# create a GUI window
gui = Tk()
#### I just design the GUI here.
#### After it is designed It ends with
gui.mainloop()
Thanks so much for your time, and this is my first post, so if I did something wrong or didn't follow the "standard entry" please correct me and let me know for the future!
The function inputError isn't defined because exec can't perform any operation that would bind local variables such as importing, assigning variables, or function/class definitions etc.
This is explained more in this SO post, or in the documentation here

Missing module attribute showing up for a linked Python script

In my learning to use Python one of the things I am trying to do is to separate like functions/details in to different scripts. In a previous script that I wrote that was a batch file renamer, I have created a GUI and I wanted to separate the GUI and its specific functions into a dedicated script that the parent script can call upon at initial opening.
The parent script is called TVShowRenamerv2.py
The GUI script is called GUI.py
From the parent script, this is imported
import tkinter as tk
from tkinter import simpledialog, filedialog, messagebox, ttk
import GUI as g
And then called on a line near the end of the script
rg = g.Renamer_GUI()
I am using VS Code as my IDE, and I get no errors prior to running the script. Once I do run the script, I get the following error:
File "TVShowRenamerv2.py", line 4, in <module>
import GUI as g
File "D:\Projects\Python\TVShowRenamer\v2\GUI.py", line 3, in <module>
import TVShowRenamerv2 as t2
File "D:\Projects\Python\TVShowRenamer\v2\TVShowRenamerv2.py", line 172, in <module>
rg = g.Renamer_GUI()
AttributeError: module 'GUI' has no attribute 'Renamer_GUI'
This is from the GUI.py
from tkinter import ttk
import TVShowRenamerv2 as t2
class Renamer_GUI():
VS Code seems to tie the two together properly because I don't get any errors when I call functions from the two scripts, so I am not sure what the issue is. Any help is greatly appreciated. Thank you.
As it turns out, I was implementing a circular import of the two different scripts (ie, both scripts were importing each other). As a more experienced Python dev friend pointed out to me, this is bad.
We initially solved the problem by placing the items that the debugger was stating as missed attributes in one of the scripts inside a name == main if statement, but that was a short term fix that ultimately ended up creating additional issues.
So I ended up creating a third script (A controller, a GUI, and now a manipulable values). The controller would create the TK window and instantiate the GUI class inside it, and then the GUI could manipulate the values in the third script. This seemed to be the better long term solution.
Thank you very much for the assistance!

PyAutoGui.pixelMatchesColor() returns impossible value, with a 10,000 usage limit?

I am creating a program to draw pictures on this site, using PyAutoGui to move the mouse, click, and check some pixel colours on the screen. You can see my testing in the top left hand corner of the canvas. My program relies heavily on the pyautogui.pixelMatchesColor() function, and at certain points my program seemed to break. After trying to find the smallest set of code which would result in the same problem, I got to this:
import pyautogui
no = 0
while True:
if pyautogui.pixelMatchesColor(1750, 180, (255, 255, -1)):
break
num += 1
print(num)
This, as you may have guessed outputted:
10000
The problem here is that once you have used the function more than 10,000 times in one run, it stop working and only returns:
(255, 255, -1)
I have looked around, but can't find anything anywhere on a usage limit of 10,000 for the pyautogui.pixelMatchesColor() function (btw this limit also applies to the pyautogui.pixel() function). It has broken my program, so if you have any information, or a way to circumvent this issue then please let me know. Thank you!
EDIT: After looking into the pyautogui code, it turns out it uses ctypes for mouse controls and PIL for screen utilities. I will try using them instead of pyautogui for more direct code to see if it makes a difference.
For anyone else encountering this bug, I've found a workaround. Instead of calling pyautogui's pixel(x, y) function (which is just a wrapper for ImageGrab's functions), call ImageGrab.grab().getpixel((x, y)) directly. The 10.000 limit is ONLY for the pyautogui.pixel(x, y) function. I don't really know why tho...
from PIL import ImageGrab
pixelRGB = ImageGrab.grab().getpixel((x, y))
Here is a screenshot of my tests with ImageGrab.grab() vs. pyautogui.pixel() (I called ImageGrab.grab() twice as often as pyautogui.pixel())
ImageGrab.grab() fail after about 10k tries of pyautogui.pixel()
And here a screenshot of ONLY ImageGrab.grab().getpixel() calls, I cancelled after x minutes, but it doesn't seem to have a limit.
ImageGrab.grab() without pyautogui.pixel() calls inbetween
Tested on:
Python 3.6.3
Pillow 6.0.0 (PIL)
PyAutoGUI 0.9.42
This might provide insight into this bug. I ran, pyautogui.pixel() until it breaks. I then tried the workaround suggested by viddle...
from PIL import ImageGrab
pixelRGB = ImageGrab.grab().getpixel((100, 125))
Which raised the following exception
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
ImageGrab.grab().getpixel((140,20))
Traceback (most recent call last):
File "", line 1, in
ImageGrab.grab().getpixel((140,20))
File "C:\Users\XisUnknown\AppData\Local\Programs\Python\Python36-32\lib\site-packages\PIL\ImageGrab.py", line 41, in grab
size, data = grabber()
OSError: screen grab failed

Appending to clipboard

I feel like I have been asking a lot of questions the last couple days but I really need help with this one. First of its my 3rd day writing code and python is the language of choice that I chose to learn to code.
OK I made this converter that converts units of measurement from mm to inches (and also converts surface finishes) I then want it to copy the converted number (taken out to the third decimal place) to the clipboard so I can paste it in another program. I am trying to do this using tkinter but I keep getting the error message
Traceback (most recent call last):
File "C:\Pygrams\Converter.py", line 104, in <module>
clipboard_append(final_form)
NameError: name 'clipboard_append' is not defined
Here is the code (only posting the part I am having trouble with) im using (assume that variables such as Results are defined elsewhere.
from tkinter import Tk
final_form = ("%.3f" % Results)
final_form2 = str(final_form)
r = Tk()
r.withdraw()
r.clipboard_clear()
clipboard_append(finalform2)
r.destroy()
What am I doing wrong?
You're calling clipboard_append(finalform2) when you should be calling r.clipboard_append(finalform2)

QT4Reactor / Scrapy / PyQt4

How to use Qt4Reactor the right way?
I have a PyQt4 Application running Scrapy to parse a website and show the results in the ui.
When the user clicks a button, the scraper gets started in another process. The ui blocks and the scraper is running. When the scraper is finished, the data is shown in the ui. What I want is a non-blockung ui when Scrapy is running.
Since Scrapy is build on top of twisted, I have to use a new process instead of a thread to start it from the ui.
My question is how to achieve a non-blocking ui as simple as possible?
I tried to use Qt4Reactor like this:
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
import qt4reactor
qt4reactor.install()
MainWindow = DiscogsRenamer()
MainWindow.show()
sys.exit(app.exec_())
reactor.runReturn()
This results in an error:
Traceback (most recent call last):
File "/home/f/work/py/discogs_renamer/main.py", line 224, in <module>
qt4reactor.install()
File "/usr/local/lib/python2.7/dist-packages/qt4reactor.py", line 338, in posixinstall
installReactor(p)
File "/usr/local/lib/python2.7/dist-packages/twisted/internet/main.py", line 32, in installReactor
raise error.ReactorAlreadyInstalledError("reactor already installed")
twisted.internet.error.ReactorAlreadyInstalledError: reactor already installed
I posted another question to this topic:
Integrate Scrapy/Twisted event loop in PyQt4 Main loop
Thanks in advance.
You must import and install() the qt4reactor before importing twisted.internet.reactor.
import qt4reactor
qt4reactor.install()
from twisted.internet import reactor

Resources