auto update port list in python - python

I want to create a user interface with tkinter and it includes reading serial ports.
I use code like this
from tkinter.ttk import Combobox
import serial
import sys
import serial.tools.list_ports
from tkinter.messagebox import showinfo
from tkinter import *
window=Tk()
window.title("test cell")
ports=list(serial.tools.list_ports.comports())
selected=StringVar(window)
m_select=Combobox(window,textvariable=selected)
m_select['values']=ports
m_select['state']='readonly'
m_select.place(x=0,y=0)
window.mainloop()
in this case I can read all connected devices but if I connect or disconnect a new device I can not see it and I have to close the file and run it again.
is there any way that I could refresh it automatically and do not need to close it??

See the below example to update the list inside the combobox when the down arrow is clicked.
I've tested this with a dummy function that returns a random number of com ports but this should work the same with the serial.tools.comports function.
(You'll need to comment back in lines that you require, I don't have serial on this PC)
from tkinter.ttk import Combobox
#import serial
import sys
#import serial.tools.list_ports
from tkinter.messagebox import showinfo
from tkinter import *
def comports():
"""Dummy function, remove me for the real thing"""
import random
ports = [f"COM{i}" for i in range(random.randint(1,10))]
return ports
def updateComPortList():
#ports=list(serial.tools.list_ports.comports())
ports = comports()
m_select['values']=ports
window=Tk()
window.title("test cell")
selected=StringVar(window)
m_select=Combobox(window,textvariable=selected,postcommand = updateComPortList)
m_select['state']='readonly'
m_select.place(x=0,y=0)
window.mainloop()

Related

Tkinter ScrolledText widget not appearing

I'm trying to add the ScrolledText widget to a Tkinter window. The program reads it perfectly as in it accepts the INSERT method for it with no errors but it's not showing up. The problem came up when I added Notebook Tabs. I've attached the code snippet. I used the place() method because I need the rest of my buttons and labels arranged in a specific pattern.
import tkinter
from tkinter import *
from tkinter import scrolledtext
from tkinter import messagebox
from tkinter import ttk
import os
import datetime
# Variables
window = Tk()
window.title("Vesnica Pomenire")
window.geometry('1500x1000')
var = IntVar()
var.set(1)
txt = scrolledtext.ScrolledText(window,width=40,height=10)
txt.place(x=50, y=50)
You're missing the mainloop()
import tkinter
from tkinter import *
from tkinter import scrolledtext
from tkinter import messagebox
from tkinter import ttk
import os
import datetime
# Variables
window = Tk()
window.title("Vesnica Pomenire")
window.geometry('1500x1000')
var = IntVar()
var.set(1)
txt = scrolledtext.ScrolledText(window,width=40,height=10)
txt.place(x=50, y=50)
window.mainloop() #You are missing this
You can read more about mainloop() here
You really missed mainloop command
window.mainloop()
add this at the bottom of your code and it will do the thing

Error with TKinter Attribute Simpledialog

I'm currently trying to write in a few basic user input boxes using the tkinter module in Python 3.6 (via Spyder). I can confirm that the module loads, and that the option to select simpledialog comes up, but I keep getting the following error:
AttributeError: module 'tkinter' has no attribute 'simpledialog'
Image of tkinter simpledialog
I've tried to look for other options, but other user input options do not seem to work on my Python interface. It either crashes, or the data isn't structured properly.
Interestingly enough, in the past, I've done similar things in Python with no errors, but this keeps coming up with this particular programming piece.
import tkinter as tk
import pyodbc as py
py.pooling = False
## INPUT YOUR USER ID AND PASSWORD AND DECLARE YOUR CONNECTION
## THE DIALOG BOXES MAY POP OPEN ON ANOTHER SCREEN
## THE PASSWORD INPUT IS MASKED AND WILL NOT SHOW IN THE
## VARIABLE EXPLORER
ID = tk.simpledialog.askstring("Please input your username.","Username: ")
PW = tk.simpledialog.askstring("Please input your password.",
"Password: ", show='*')
CONN = tk.simpledialog.askstring("Please input your connection.",
"Connection: ")
My expected results are that a popup window will appear and that I'll be able to get the user information I need to maintain a stable connection to the server I'm using.
Thank you in advance for your advice!
simpledialog is not in tkinter but in tkinter.simpledialog and you have to import it
import tkinter as tk
import tkinter.simpledialog
root = tk.Tk() # create main window
#root.iconify() # minimize main window
root.withdraw() # hide main window
answer = tkinter.simpledialog.askstring("Question", 'Your name:')
print(answer)
#root.destroy() # should work without it
#root.mainloop() # should work without it
See tkinter modules
import tkinter as tk
from tkinter import simpledialog
root = tk.Tk()
ID = simpledialog.askstring("Please input your username.", "Username: ", parent=root)
root.mainloop()
This will keep the popup within the parent window and visible.

I keep getting an error when I try to import tkFileDialog

I am following this tutorial to create my own simple text editor. However, I am coming across an error I don't know how to fix. I'm running this code:
from tkinter import *
import tkinter.tkFileDialog
I've also tried this:
import tkinter
import tkinter.tkFileDialog
Both of them give me this error:
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
import tkinter.tkFileDialog
ModuleNotFoundError: No module named 'tkinter.tkFileDialog'
I'm doing exactly what the tutorial said to do, but it won't work. Why is this happening?
For reference, I am using python 3.7 64-bit on windows 10.
Python 3 tkinter does not have a tkFileDialog import. Instead you want to import filedialog like this.
import tkinter as tk # this is the preferred import for tkinter
from tkinter import filedialog
root = tk.Tk()
x = filedialog.askopenfilename()
print(x)
root.mainloop()
If you would prefer to only import the dialog's you specifically need you can do something like this.
import tkinter as tk # this is the preferred import for tkinter
from tkinter.filedialog import askopenfilename
root = tk.Tk()
x = askopenfilename()
print(x)
root.mainloop()
Update: Based on what Bryan has mentioned in the below here is another example that includes a delay to help prevent the issue mentioned. Though this only applies to dilogs opened before the mainloop has been reached and for many applications I would think this is not an issue as dialog is not often the first thing you have up in a GUI. However it is still good information to have.
import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
def print_file_name():
x = filedialog.askopenfilename()
print(x)
root.after(100, print_file_name)
root.mainloop()
Or:
import tkinter as tk # this is the preferred import for tkinter
from tkinter.filedialog import askopenfilename
root = tk.Tk()
def print_file_name():
x = askopenfilename()
print(x)
root.after(100, print_file_name)
root.mainloop()

Using the after-method with Tkinter

I'm having troubles using the "after" method in my GUI.
The goal is to create a loop, which calculates "flow" with given input variables.
So far I didn't manage to get my code running, with the documentation on "after" or this post Tkinter only calls after_idle once
My Code:
import Tkinter as tk
from Tkinter import *
import ttk
import tkMessageBox
class Regeln():
def __init__(self):
bla=1
def lesen(self,faktor,stromdichte,flaeche,anzahl,elektronen,konzentration):
self.faktor=faktor
self.stromdichte=stromdichte
self.flaeche=flaeche
self.anzahl=anzahl
self.elektronen=elektronen
self.konzentration=konzentration
try:
self.faktor=float(self.faktor)
self.stromdichte=float(self.stromdichte)
self.flaeche=float(self.flaeche)
self.anzahl=float(self.anzahl)
self.elektronen=float(self.elektronen)
self.konzentration=float(self.konzentration)
except:
tkMessageBox.showerror("Achtung!","Nur Zahlen eingeben!")
try:
1/(self.faktor*self.stromdichte*self.flaeche*self.anzahl*self.elektronen*self.konzentration)
except:
tkMessageBox.showerror("Achtung!","Nur Werte größer 0 eingeben!")
self.algorithmus()
def algorithmus(self):
flow=self.faktor*self.stromdichte*self.elektronen*60/(96485.34*self.konzentration*0.75/100)*self.flaeche*self.anzahl/1000
print flow
self.after(1500,self.algorithmus)
With this I get an "AttributeError". Anybody has any idea how to get it running?
after is a method available on all tkinter widgets. In your specific case, self is not a widget, so naturally it won't have this method.
You need to call after from an existing widget. For example, if you initially created your GUI with something like this:
root = tk.Tk()
You can later call after like this:
root.after(...)

Tkinter: menu not displayed

I run this code which aim is only to display a menu bar.
There is a simple menu bar in which 3 sub-menus are created without performing anything except for the Exit one which closes the window:
from Tkinter import *
import tkMessageBox
import numpy as np
import ttk
import tkFont
from PIL import ImageTk, Image
from tkColorChooser import askcolor
from tkFileDialog import askopenfilename
class MyGui(Frame):
def __init__(self,master):
Frame.__init__(self,master)
self.master=master
self.themenus() # menu initialization within the constructor
def themenus(self):
self.menubar=Menu(self.master)
self.filemenu=Menu(self.menubar,tearoff=0)
self.filemenu.add_command(label="Open Image")
self.filemenu.add_command(label="Save Image")
self.filemenu.add_command(label="Exit",command=self.master.quit)
self.menubar.add_cascade(label="File",menu=self.filemenu)
if __name__=="__main__":
root=Tk()
root.wm_title("Test")
mg=MyGui(root)
root.mainloop()
I get this error:
libdc1394 error: Failed to initialize libdc1394
How to fix this ?
EDIT:
I resolved the problem by removing away the original imports that I did not use after all:
import tkMessageBox
import numpy as np
import ttk
import tkFont
from PIL import ImageTk, Image
from tkColorChooser import askcolor
from tkFileDialog import askopenfilename
Now, no error is triggered, however I do not see the menu displayed. Why ?
I resolved my problem by adding this line at the end of themenus() function:
self.master.config(menu=self.menubar)

Categories