Search code examples
pythonuser-interfacetkintercomboboxcustomtkinter

Getting a value from custom tkinter combobox


this is my code , in class cfgframe / create widget function ,i am trying to set the options in the config.ini file to the value selected in the combobox i tried many solutions but i couldnt get any to work can you please help me because i am kind of new to this the print(choice) prints some weird things like <bound method StringVar.get of <tkinter.StringVar object at 0x00000000078C4450>> then the combobox stoppes calling the function


# importing modules #

from configparser import ConfigParser
from tkinter.constants import *
from PyPDF2 import PdfMerger
import customtkinter as ctk
from time import sleep
from PIL import Image
import tkinter as tk
import pystray
import pytube
import sys
import os

# loading config #

Config = ConfigParser()
Config.read(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\config.ini")


# defining classes #

class App(ctk.CTk):
    def __init__(self):
        super().__init__()

        # main setup #
        self.title(cfg("title"))
        self.geometry(cfg("resolution"))
        self.resizable(cfg("resizable"),cfg("resizable"))
        self._set_appearance_mode(cfg("appearance_mode"))
        self.attributes("-topmost",cfg("topmost"))
        self.title(cfg("title"))

        # Frames #

        self.SM = SMFrame(self)
        self.PDF = PDFFrame(self)
        self.YT = YTFrame(self)
        self.Cfg = CfgFrame(self)
        self.Animated_bar = PanelFrame(self, -0.2, 0)
        

        self.Frames = [self.SM, self.PDF , self.YT , self.Cfg]

        def frameswitch(self,target):
            for Frame in self.Frames :
                if Frame != target:
                    Frame.pack_forget()
                else:
                    Frame.pack(expand=True,fill="both")

        # creating buttons #

        bar = ctk.CTkLabel(self.Animated_bar,fg_color="#"+str(cfg("sidebar_colour")),width=80,height=720,text=None).place(relx=0.79,rely=0)

        def ButtonFunc(self,target):
            frameswitch(self,target)
            self.Animated_bar.Animate()

        def create_Buttons(self):
            SMBtn = ctk.CTkButton(
                self.Animated_bar,
                text="Scrip Manger",
                fg_color="transparent",
                width=268,
                height=80,
                hover=False,
                font=("Airel",20),
                corner_radius=0,
                command=lambda:ButtonFunc(self,self.SM)).place(x=0,y=0)
            
            PDFBtn = ctk.CTkButton(
                self.Animated_bar,
                text="PDF Merger",
                fg_color="transparent",
                width=268,height=80,
                hover=False,
                font=("Airel",20),
                corner_radius=0,
                command=lambda:ButtonFunc(self,self.PDF)).place(x=0,y=80)
            YTBtn = ctk.CTkButton(
                self.Animated_bar,
                text="Youtube Downloader",
                fg_color="transparent",
                width=268,height=80,
                hover=False,
                font=("Airel",20),
                corner_radius=0,
                command=lambda:ButtonFunc(self,self.YT)).place(x=0,y=160)
            
            CfgBtn = ctk.CTkButton(
                self.Animated_bar,
                text="Settings",fg_color="transparent",
                width=220,
                height=80,
                hover=False,
                font=("Airel",20),
                corner_radius=0,
                command=lambda:ButtonFunc(self,self.Cfg)).place(x=40,y=638)
            
            CfgBtn2 = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\cogwheel.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidepanel_colour")),
                width=80,
                height=90,
                command=lambda:ButtonFunc(self,self.Cfg)).place(relx=0,rely=0.88)

            ArrowBtn = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\arrows.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidebar_colour")),
                width=80,
                height=90,
                command=self.Animated_bar.Animate).place(relx=0.79,rely=0.88)
            
            SMBtn2 = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\script.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidebar_colour")),
                width=80,
                height=85,
                command=lambda:frameswitch(self,self.SM)).place(relx=0.79,rely=0)
            
            PDFBtn2 = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\PDF.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidebar_colour")),
                width=80,
                height=85,
                command=lambda:frameswitch(self,self.PDF)).place(relx=0.79,rely=0.11)
            
            YTBtn2 = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\youtube-logo.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidebar_colour")),
                width=80,
                height=85,
                command=lambda:frameswitch(self,self.YT)).place(relx=0.79,rely=0.22)

        create_Buttons(self)

            # run #

        self.mainloop()

class PanelFrame(ctk.CTkFrame):
    def __init__(self,parent,start,end):
        super().__init__(parent,fg_color="#"+str(cfg("sidepanel_colour")))
        self.start = start
        self.end = end
        self.width = abs(start-end)+0.05
        self.pos = self.start
        self.in_start_pos = True
        self.place(relx=self.start, rely=0, relwidth=self.width,relheight=1)
        
    def Animate(self):
        if self.in_start_pos == True:
            self.Animate_backwards()
        else:
            self.Animate_forward()
    
    def Animate_forward(self):
        if self.pos > self.start:
            self.pos -= 0.008
            self.place(relx=self.pos, rely=0, relwidth=self.width,relheight=1)
            self.after(10,self.Animate_forward)
        else:
            self.in_start_pos = True
    
    def Animate_backwards(self):
        if self.pos < self.end:
            self.pos += 0.008
            self.place(relx=self.pos, rely=0, relwidth=self.width,relheight=1)
            self.after(10,self.Animate_backwards)
        else:
            self.in_start_pos = False
            
class SMFrame(ctk.CTkFrame):
    def __init__(self,parent):
        super().__init__(parent,fg_color="#"+str(cfg("main_colour")))
        self.pack(expand=True,fill="both")
        self.create_widgets()

    def create_widgets(self):
        pass

class PDFFrame(ctk.CTkFrame):
    def __init__(self,parent):
        super().__init__(parent,fg_color="#"+str(cfg("main_colour")))
        self.create_widgets()

    def create_widgets(self):
        pass
    
class YTFrame(ctk.CTkFrame):
    def __init__(self,parent):
        super().__init__(parent,fg_color="#"+str(cfg("main_colour")))
        self.create_widgets()

    def create_widgets(self):
        pass
    
class CfgFrame(ctk.CTkFrame):
    def __init__(self,parent):
        super().__init__(parent,fg_color="#"+str(cfg("main_colour")))
        self.create_widgets()

    def create_widgets(self):
        res_list = ["1920x1080","1600x900","1280x720","1024x768","800,600"]
        Current_res = ctk.StringVar(value=cfg("resolution"))
        ctk.CTkLabel(self,text=("Settings"),font=("Airel",60)).place(rely=0.05,relx=0.45)
        resolution = ctk.CTkComboBox(self,values=res_list,variable=Current_res,command=Changeini("resolution",Current_res.get)) 
        resolution.pack()                                                      # ^^^^^^^^^^^^^^^^^^ #  
                                                                                
        
# defining functions #

def cfg(option):
    return Config.get("Default",option)

def Changeini(option,choice):
    Config.set(section="Default",option=option,value=str(choice))
    print(choice)

def getImage(path):
   return ctk.CTkImage(Image.open(path))

def get_path(filename):
    if hasattr(sys, "_MEIPASS"):
        return os.path.join(sys._MEIPASS, filename)
    else:
        return filename

# runtime #

App()

i also tried this

# importing modules #

from configparser import ConfigParser
from tkinter.constants import *
from PyPDF2 import PdfMerger
import customtkinter as ctk
from time import sleep
from PIL import Image
import tkinter as tk
import pystray
import pytube
import sys
import os

# loading config #

Config = ConfigParser()
Config.read(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\config.ini")


# defining classes #

class App(ctk.CTk):
    def __init__(self):
        super().__init__()

        # main setup #
        self.title(cfg("title"))
        self.geometry(cfg("resolution"))
        self.resizable(cfg("resizable"),cfg("resizable"))
        self._set_appearance_mode(cfg("appearance_mode"))
        self.attributes("-topmost",cfg("topmost"))
        self.title(cfg("title"))

        # Frames #

        self.SM = SMFrame(self)
        self.PDF = PDFFrame(self)
        self.YT = YTFrame(self)
        self.Cfg = CfgFrame(self)
        self.Animated_bar = PanelFrame(self, -0.2, 0)
        

        self.Frames = [self.SM, self.PDF , self.YT , self.Cfg]

        def frameswitch(self,target):
            for Frame in self.Frames :
                if Frame != target:
                    Frame.pack_forget()
                else:
                    Frame.pack(expand=True,fill="both")

        # creating buttons #

        bar = ctk.CTkLabel(self.Animated_bar,fg_color="#"+str(cfg("sidebar_colour")),width=80,height=720,text=None).place(relx=0.79,rely=0)

        def ButtonFunc(self,target):
            frameswitch(self,target)
            self.Animated_bar.Animate()

        def create_Buttons(self):
            SMBtn = ctk.CTkButton(
                self.Animated_bar,
                text="Scrip Manger",
                fg_color="transparent",
                width=268,
                height=80,
                hover=False,
                font=("Airel",20),
                corner_radius=0,
                command=lambda:ButtonFunc(self,self.SM)).place(x=0,y=0)
            
            PDFBtn = ctk.CTkButton(
                self.Animated_bar,
                text="PDF Merger",
                fg_color="transparent",
                width=268,height=80,
                hover=False,
                font=("Airel",20),
                corner_radius=0,
                command=lambda:ButtonFunc(self,self.PDF)).place(x=0,y=80)
            YTBtn = ctk.CTkButton(
                self.Animated_bar,
                text="Youtube Downloader",
                fg_color="transparent",
                width=268,height=80,
                hover=False,
                font=("Airel",20),
                corner_radius=0,
                command=lambda:ButtonFunc(self,self.YT)).place(x=0,y=160)
            
            CfgBtn = ctk.CTkButton(
                self.Animated_bar,
                text="Settings",fg_color="transparent",
                width=220,
                height=80,
                hover=False,
                font=("Airel",20),
                corner_radius=0,
                command=lambda:ButtonFunc(self,self.Cfg)).place(x=40,y=638)
            
            CfgBtn2 = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\cogwheel.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidepanel_colour")),
                width=80,
                height=90,
                command=lambda:ButtonFunc(self,self.Cfg)).place(relx=0,rely=0.88)

            ArrowBtn = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\arrows.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidebar_colour")),
                width=80,
                height=90,
                command=self.Animated_bar.Animate).place(relx=0.79,rely=0.88)
            
            SMBtn2 = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\script.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidebar_colour")),
                width=80,
                height=85,
                command=lambda:frameswitch(self,self.SM)).place(relx=0.79,rely=0)
            
            PDFBtn2 = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\PDF.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidebar_colour")),
                width=80,
                height=85,
                command=lambda:frameswitch(self,self.PDF)).place(relx=0.79,rely=0.11)
            
            YTBtn2 = ctk.CTkButton(
                self.Animated_bar,
                text=None,
                image=getImage(r"C:\Users\myz-pc\Documents\vscode\python\PowerMods\Icons\youtube-logo.png"),
                fg_color="transparent",
                hover=False,
                bg_color="#"+str(cfg("sidebar_colour")),
                width=80,
                height=85,
                command=lambda:frameswitch(self,self.YT)).place(relx=0.79,rely=0.22)

        create_Buttons(self)

            # run #

        self.mainloop()

class PanelFrame(ctk.CTkFrame):
    def __init__(self,parent,start,end):
        super().__init__(parent,fg_color="#"+str(cfg("sidepanel_colour")))
        self.start = start
        self.end = end
        self.width = abs(start-end)+0.05
        self.pos = self.start
        self.in_start_pos = True
        self.place(relx=self.start, rely=0, relwidth=self.width,relheight=1)
        
    def Animate(self):
        if self.in_start_pos == True:
            self.Animate_backwards()
        else:
            self.Animate_forward()
    
    def Animate_forward(self):
        if self.pos > self.start:
            self.pos -= 0.008
            self.place(relx=self.pos, rely=0, relwidth=self.width,relheight=1)
            self.after(10,self.Animate_forward)
        else:
            self.in_start_pos = True
    
    def Animate_backwards(self):
        if self.pos < self.end:
            self.pos += 0.008
            self.place(relx=self.pos, rely=0, relwidth=self.width,relheight=1)
            self.after(10,self.Animate_backwards)
        else:
            self.in_start_pos = False
            
class SMFrame(ctk.CTkFrame):
    def __init__(self,parent):
        super().__init__(parent,fg_color="#"+str(cfg("main_colour")))
        self.pack(expand=True,fill="both")
        self.create_widgets()

    def create_widgets(self):
        pass

class PDFFrame(ctk.CTkFrame):
    def __init__(self,parent):
        super().__init__(parent,fg_color="#"+str(cfg("main_colour")))
        self.create_widgets()

    def create_widgets(self):
        pass
    
class YTFrame(ctk.CTkFrame):
    def __init__(self,parent):
        super().__init__(parent,fg_color="#"+str(cfg("main_colour")))
        self.create_widgets()

    def create_widgets(self):
        pass
    
class CfgFrame(ctk.CTkFrame):
    def __init__(self,parent):
        super().__init__(parent,fg_color="#"+str(cfg("main_colour")))
        self.create_widgets()

    def create_widgets(self):
        def getvalue(event):
            print(resolution.get)
            print(Current_res.get)
        res_list = ["1920x1080","1600x900","1280x720","1024x768","800,600"]
        Current_res = ctk.StringVar(value=cfg("resolution"))
        ctk.CTkLabel(self,text=("Settings"),font=("Airel",60)).place(rely=0.05,relx=0.45)
        resolution = ctk.CTkComboBox(self,values=res_list,variable=Current_res)
        resolution.bind("<<ComboboxSelected>>",getvalue)
        resolution.pack()
        

# defining functions #

def cfg(option):
    return Config.get("Default",option)

def Changeini(option,choice):
    Config.set(section="Default",option=option,value=str(choice))
    print(choice)

def getImage(path):
   return ctk.CTkImage(Image.open(path))

def get_path(filename):
    if hasattr(sys, "_MEIPASS"):
        return os.path.join(sys._MEIPASS, filename)
    else:
        return filename

# runtime #

App()

also this is the config

[Default]
resolution = 1280x720
title = PowerMods
resizable = False
appearance_mode = dark
topmost = True
sidebar_colour = 101010
sidepanel_colour = 151515
main_colour = 403030

adding lambda : to the command=changeini gaves me this error

Traceback (most recent call last):
  File "C:\Python\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:\Python\Lib\site-packages\customtkinter\windows\widgets\core_widget_classes\dropdown_menu.py", line 101, in <lambda>
    command=lambda v=value: self._button_callback(v),
                            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python\Lib\site-packages\customtkinter\windows\widgets\core_widget_classes\dropdown_menu.py", line 106, in _button_callback
    self._command(value)
  File "C:\Python\Lib\site-packages\customtkinter\windows\widgets\ctk_combobox.py", line 384, in _dropdown_callback
    self._command(value)
TypeError: CfgFrame.create_widgets.<locals>.<lambda>() takes 0 positional arguments but 1 was given

Solution

  • Note that command=Changeini("resolution",Current_res.get) will execute Changeini(...) immediately and assign its result (which is None) to command option.

    You need to use lambda instead:

    resolution = ctk.CTkComboBox(self, values=res_list, variable=Current_res,
                                 command=lambda value: Changeini("resolution", value))