Tk_GetPixmap : Erreur lors de la création de la section DIB.
Hello,
I want to create software that allows the creation of interfaces. There are "Add a button", "Change the title", and I will add other functionalities. When I create a button with nbtn (newbutton), a message box appears:
- Title: Tk_GetPixmap: Error from CreateDIBSection
- Content: The operation was successful
Once I close it, my main window also closes. I am searching online but finding nothing, which is why I am coming to ask you.
Code:
import uuid from pc import infos import tkinter as tk from tkinter import ttk from PIL import Image, ImageTk import customtkinter as ctk from tkinter import simpledialog import os import webcolors from customtkinter import CTkImage class MultiEntryDialog(ctk.CTkToplevel): def __init__(self, parent, title, entries: list): super().__init__(parent) self.title(title) self.entries = [] for i, entry_name in enumerate(entries): ctk.CTkLabel(self, text=f"{entry_name}:").grid(row=i, sticky="w") entry = ctk.CTkEntry(self) entry.grid(row=i, column=1) self.entries.append(entry) button_frame = ctk.CTkFrame(self) button_frame.grid(row=len(entries), columnspan=2, pady=10) ok_button = ctk.CTkButton(button_frame, text="OK", command=self.ok) ok_button.pack(side="left") cancel_button = ctk.CTkButton(button_frame, text="Cancel", command=self.cancel) cancel_button.pack(side="left") self.result = None self.transient(parent) self.grab_set() while self.winfo_exists(): parent.update() if self.result is None: self.result = ['', '', ''] def ok(self): result = [entry.get() for entry in self.entries] self.destroy() self.result = result def cancel(self): self.destroy() self.result = ['', '', ''] class Constructor: objects = [] objects_id = [] def __init__(self): pass class App: memory = [] frames = [] buttons = [] def cthex(self, all_form): try: color = webcolors.rgb_to_hex(all_form) except: try: color = webcolors.name_to_hex(all_form) except Exception as e: color = all_form return color def add_frame(self, win, name, rw, rh, rx, ry, bg, bdw=0): frame = ctk.CTkFrame(win, width=(infos.screen_size_x * rw), height=(infos.screen_size_y * rh), fg_color=bg, border_width=bdw) frame.place(x=(infos.screen_size_x * rx), y=(infos.screen_size_y * ry)) if self.search_frame(name)[0]: raise RuntimeWarning(f'Frame "{name}" already exists.') self.frames.append([str(name), frame]) def search_frame(self, name): for i, frm_infos in enumerate(self.frames): if name == frm_infos[0]: return True, i return False, 0 def rem_frame(self, name): ex, i = self.search_frame(name) if not ex: raise RuntimeWarning(f'Frame {name} doesn\'t exist.') self.frames[i][1].destroy() del self.frames[i] def add_button(self, win, name, rw, rh, rx, ry, bg, bdw=0, command='', text='', image=''): if not command: command = 'None' if not bg: bg = '#6292bd' hex = self.cthex(bg) rvb = [] rvb2 = [] for p in webcolors.hex_to_rgb(hex): rvb.append(int(p)) rvb2.append(int(p)) for primary in range(len(rvb2)): rvb2[primary] += 10 hex2 = webcolors.rgb_to_hex(rvb2) w, h = int(infos.screen_size_x * rw), int(infos.screen_size_y * rh) if image: img = Image.open(image) img.thumbnail((w ** 1, h ** 1)) imgtk = CTkImage(img) else: img = Image.new('RGB', (1, 1), tuple(rvb)) imgtk = CTkImage(img) imgtk.configure(size=(1, 1)) if img.width + len(text) * 8 > w and image: w += (img.width + len(text) * 8) - w self.memory.append(imgtk) button = ctk.CTkButton(win, image=imgtk, text=text, width=w, height=h, command=eval(command), compound='left', border_width=bdw, fg_color=bg, bg_color='#2b2b2b', hover_color=hex2) button.place(x=(infos.screen_size_x * rx - w / 2), y=(infos.screen_size_y * ry + h / 2) + 1) if self.search_frame(name)[0]: raise RuntimeWarning(f'Frame "{name}" already exists.') self.buttons.append([str(name), button, imgtk]) def search_button(self, name): for i, btn_infos in enumerate(self.buttons): if name == btn_infos[0]: return True, i return False, 0 def rem_button(self, name): ex, i = self.search_button(name) if not ex: raise RuntimeWarning(f'Button {name} doesn\'t exist.') self.buttons[i][1].destroy() del self.buttons[i] def update_theme(self, theme): ctk.set_appearance_mode(theme) self.theme = theme def title(self): dialog = MultiEntryDialog(self.win, '', ['New title']) self.win.title(dialog.result[0]) def nbtn(self): x, y = 0, 0 w, h = 0, 0 sx, sy = infos.screen_size_x, infos.screen_size_y new_button = ctk.CTkButton(master=self.win, text='', compound='left') while not infos.is_clicking: pass while infos.is_clicking: pass while not infos.is_clicking: x, y = infos.get_pos() w, h = new_button.winfo_width(), new_button.winfo_height() new_button.place(x=x * 0.8 - w // 2.5, y=y * 0.8 - h) self.win.update() rx, ry = (x * 0.8 - w // 2.5) / infos.screen_size_x, (y * 0.8 - h) / infos.screen_size_y dialog = MultiEntryDialog(self.win, 'New Button', ['Text', 'Color', 'Command']) if not dialog.result[0]: print(dialog.result) new_button.destroy() return None if not dialog.result[2]: dialog.result[2] = '' name = uuid.uuid4() self.add_button(self.win, name, w, h, rx, ry, bg=dialog.result[1], bdw=0, command=dialog.result[2], text=dialog.result[0], image='') self.win.update() new_button.destroy() self.file_write( f'objects.append(["button", ["{name}", 0.03, 0.02, {rx}, {ry}, "#282d36", 0, "pass", "{dialog.result[0]}", ""]])\n') def file_write(self, to_write): self.file_result.write(to_write) def __init__(self, title='Windows Tool Kit Interface Creator', theme=None, background='white', style='default', logo_path=None, objects=None): self.theme = None basic = open('basic', 'r') self.file_result = open('result.py', 'w') self.file_result.write(basic.read() + '\nobjects = []\n') if objects is None: objects = [] self.win = ctk.CTk() if theme: try: self.update_theme(theme) except: raise RuntimeWarning(f'Theme {theme} doesn\'t exist') self.win.geometry(f'{infos.screen_size_x}x{infos.screen_size_y}') self.win.title(title) self.win.state('zoomed') self.win.iconbitmap(logo_path) self.win.configure(background=background) self.style = ttk.Style() self.style.theme_use(style) for _type, args in objects: if _type == 'frame': self.add_frame(self.win, args[0], args[1], args[2], args[3], args[4], args[5], args[6]) elif _type == 'button': self.add_button(self.win, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]) if logo_path: p1 = tk.PhotoImage(file=logo_path) self.win.iconphoto(False, p1) while True: try: self.win.winfo_exists() except: break self.win.update() App(background='dark gray', theme='Dark', style='vista', logo_path='logo.png', objects=[['frame', ['lbframe', 0.1, 1, 0, 0, '#2b2b2b', 0]], ['frame', ['rbframe', 0.1, 1, 0.9, 0, '#282d36', 0]], ['frame', ['cbar', 1, 0.03, 0, 0, '#2b2b2b', 0]], ['button', ['b1', 0.03, 0.02, 0.03, 0.05, '#282d36', 0, 'self.title', 'Change Title', '']], ['button', ['b1', 0.03, 0.02, 0.03, 0.08, '#282d36', 0, 'self.nbtn', 'Add Button', '']], ])
6 answers
-
Hello,
It's hard to help you with such code:
Imports that we don't know.
A file for reading and writing whose content we are not aware of (which is also not closed, by the way).
You need to post a minimal code that generates this error.
-
Ok ????.
Here are the 2 methods that may generate errors:def add_button(self, win, name, rw, rh, rx, ry, bg, bdw=0, command='', text='', image=''): if not command: command = 'None' if not bg: bg = '#6292bd' hex = self.cthex(bg) rvb = [] rvb2 = [] for p in webcolors.hex_to_rgb(hex): rvb.append(int(p)) rvb2.append(int(p)) for primary in range(len(rvb2)): rvb2[primary] += 10 hex2 = webcolors.rgb_to_hex(rvb2) w, h = int(infos.screen_size_x * rw), int(infos.screen_size_y * rh) if image: img = Image.open(image) img.thumbnail((w ** 1, h ** 1)) imgtk = CTkImage(img) else: img = Image.new('RGB', (1, 1), tuple(rvb)) imgtk = CTkImage(img) imgtk.configure(size=(1, 1)) if img.width + len(text) * 8 > w and image: w += (img.width + len(text) * 8) - w self.memory.append(imgtk) button = ctk.CTkButton(win, text=text, width=w, height=h, command=eval(command), compound='left', border_width=bdw, fg_color=bg, bg_color='#2b2b2b', hover_color=hex2) button.place(x=(infos.screen_size_x * rx - w / 2), y=(infos.screen_size_y * ry + h / 2) + 1) if self.search_frame(name)[0]: raise RuntimeWarning(f'Frame "{name}" already exists.') self.buttons.append([str(name), button, imgtk])def nbtn(self): x, y = 0, 0 w, h = 0, 0 sx, sy = infos.screen_size_x, infos.screen_size_y new_button = ctk.CTkButton(master=self.win, text='', compound='left') while not infos.is_clicking: pass while infos.is_clicking: pass while not infos.is_clicking: x, y = infos.get_pos() w, h = new_button.winfo_width(), new_button.winfo_height() new_button.place(x=x * 0.8 - w // 2.5, y=y * 0.8 - h) self.win.update() rx, ry = (x * 0.8 - w // 2.5) / infos.screen_size_x, (y * 0.8 - h) / infos.screen_size_y dialog = MultiEntryDialog(self.win, 'New Button', ['Text', 'Color', 'Command']) if not dialog.result[0]: print(dialog.result) new_button.destroy() return None if not dialog.result[2]: dialog.result[2] = '' name = uuid.uuid4() self.add_button(self.win, name, w, h, rx, ry, bg=dialog.result[1], bdw=0, command=dialog.result[2], text=dialog.result[0], image='') self.win.update() new_button.destroy() self.file_write( f'objects.append(["button", ["{name}", 0.03, 0.02, {rx}, {ry}, "#282d36", 0, "pass", "{dialog.result[0]}", ""]])\n')
Unknown imports:I import the infos class from pc.py which contains information about the computer, such as screen dimensions (infos.screen_sizex...), mouse positions (infos.get_pos())
nbtn consists of creating a temporary button that will move with the mouse
until clicked on the screen (to place it), once placed, it opens a dialog box to ask what should be written in it, the color and the command.Once the user closes the dialog box, the temporary button is
destroyed to create a new one with self.add_button()And from the moment I enter the button information, the error occurs, as mentioned earlier.
-
-
Hello,
Is this what you call a minimalist code?
What is import uuid?
Moreover, you need to post the code this way:
https://codes-sources.commentcamarche.net/faq/11288-poster-un-extrait-de-code
Visually, it should look like this:
for k in range(10): print(k)
-
@Noa, just to clarify Phil's request, your code needs to be executable as is, with a simple copy-paste, and trigger the error.
- It should not depend on third-party files (unless you include their content, ideally minimal)
- It should not depend on modules (unless those modules are standard or you indicate how to retrieve them).
If we cannot reproduce your issue, it is difficult to understand its cause.
@Phil_1857 StatusMember
What is import uuid?
On my end, this module seems to exist by default (I did not install it via PIP or APT) and I have seen it in code before. If needed, the module in question is available on pypi (see this link) and is presented here.
-
-
import uuid import tkinter as tk from tkinter import ttk from PIL import Image, ImageTk import customtkinter as ctk import os import webcolors from customtkinter import CTkImage class infos: import ctypes import pyautogui from pynput import mouse def on_mouse_press(x, y, button, pressed): if pressed: infos.is_clicking = True else: infos.is_clicking = False @staticmethod def get_titlebar_size(): SM_CYSIZE = 31 user32 = infos.ctypes.windll.user32 titlebar_height = user32.GetSystemMetrics(SM_CYSIZE) return titlebar_height @staticmethod def get_pos(): infos.current_mouse_x = infos.pyautogui.position()[0] infos.current_mouse_y = infos.pyautogui.position()[1] return infos.current_mouse_x, infos.current_mouse_y @staticmethod def on_click(x, y, button, pressed): if button == mouse.Button.left: infos.is_clicking = True else: infos.is_clicking = False user32 = ctypes.windll.user32 screen_size_x = user32.GetSystemMetrics(0) screen_size_y = user32.GetSystemMetrics(1) center_screen_x = screen_size_x // 2 center_screen_y = screen_size_y // 2 ratio = screen_size_x / screen_size_y pxl_size_x = screen_size_x // 480 pxl_size_y = screen_size_y // 360 current_mouse_x, current_mouse_y = 0, 0 is_clicking = False mouseListener = mouse.Listener(on_click=on_mouse_press) mouseListener.start() @staticmethod def ctr(xy: list): rx = xy[0] / infos.screen_size_x ry = xy[1] / infos.screen_size_y return [rx, ry] class MultiEntryDialog(ctk.CTkToplevel): def __init__(self, parent, title, entries: list): super().__init__(parent) self.title(title) self.entries = [] for i, entry_name in enumerate(entries): ctk.CTkLabel(self, text=f"{entry_name}:")\ .grid(row=i, sticky="w") entry = ctk.CTkEntry(self) entry.grid(row=i, column=1) self.entries.append(entry) button_frame = ctk.CTkFrame(self) button_frame.grid(row=len(entries), columnspan=2, pady=10) ok_button = ctk.CTkButton(button_frame, text="OK" , command=self.ok) ok_button.pack(side="left") cancel_button = ctk.CTkButton(button_frame, text="Annuler", command=self.cancel) cancel_button.pack(side="left") self.result = None self.transient(parent) self.grab_set() while self.winfo_exists(): parent.update() if self.result is None: self.result = [''] * len(entries) def ok(self): result = [entry.get() for entry in self.entries] self.destroy() self.result = result def cancel(self): self.destroy() class Constructor: objects = [] objects_id = [] def __init__(self): pass class App: memory = [] frames = [] buttons = [] def cthex(self, all_form): try: color = webcolors.rgb_to_hex(all_form) except: try: color = webcolors.name_to_hex(all_form) except Exception as e: color = all_form return color def add_frame(self, win, name, rw, rh, rx, ry, bg, bdw=0): frame = ctk.CTkFrame(win, width=(infos.screen_size_x * rw), height=(infos.screen_size_y * rh), fg_color=bg, border_width=bdw) frame.place(x=(infos.screen_size_x * rx), y=(infos.screen_size_y * ry)) if self.search_frame(name)[0]: raise RuntimeWarning(f'Frame "{name}" already exists.') self.frames.append([str(name), frame]) def search_frame(self, name): for i, frm_infos in enumerate(self.frames): if name == frm_infos[0]: return True, i return False, 0 def rem_frame(self, name): ex, i = self.search_frame(name) if not ex: raise RuntimeWarning(f'Frame {name} doesn\'t exist.') self.frames[i][1].destroy() del self.frames[i] def add_button(self, win, name, rw, rh, rx, ry, bg, bdw=0, command='', text='', image=''): if not bg: bg = '#FF0000' rvb1 = webcolors.hex_to_rgb(bg) rvb2 = rvb1 new_rvb = [] for p in rvb2: new_rvb.append(p + 50) hex1 = webcolors.rgb_to_hex(new_rvb) if not command: command = 'lambda: None' w, h = int(infos.screen_size_x * rw),\ int(infos.screen_size_y * rh) if image: img = Image.open(image) img.thumbnail((w ** 1, h ** 1)) imgtk = CTkImage(img) else: img = Image.new('RGB', (1, 1), rvb1) imgtk = CTkImage(img) imgtk.configure(size=(1, 1)) if img.width + len(text) * 8 > w and image: w += (img.width + len(text) * 8) - w self.memory.append(imgtk) button = ctk.CTkButton(win, text=text, width=w, height=h, command=eval(command), compound='left', border_width=bdw, fg_color=bg, bg_color='#2b2b2b', hover_color=hex1) button.place(x=(infos.screen_size_x * rx - w / 2), y=(infos.screen_size_y * ry + h / 2) + 1) if self.search_frame(name)[0]: raise RuntimeWarning(f'Frame "{name}" already exists.') self.buttons.append([str(name), button, imgtk]) def search_button(self, name): for i, btn_infos in enumerate(self.buttons): if name == btn_infos[0]: return True, i return False, 0 def rem_button(self, name): ex, i = self.search_button(name) if not ex: raise RuntimeWarning(f'Button {name} doesn\'t exist.') self.buttons[i][1].destroy() del self.buttons[i] def update_theme(self, theme): ctk.set_appearance_mode(theme) self.theme = theme def title(self): dialog = MultiEntryDialog(self.win, '', ['New title']) self.win.title(dialog.result[0]) def nbtn(self): x, y = 0, 0 w, h = 0, 0 sx, sy = infos.screen_size_x, \ infos.screen_size_y new_button = ctk.CTkButton(master=self.win, text='', compound='left') while not infos.is_clicking: pass while infos.is_clicking: pass while not infos.is_clicking: x, y = infos.get_pos() w, h = new_button.winfo_width(), \ new_button.winfo_height() new_button.place(x=x * 0.8 - w // 2.5, y=y * 0.8 - h) self.win.update() rx, ry = (x * 0.8 - w // 2.5) / infos.screen_size_x, \ (y * 0.8 - h) / infos.screen_size_y dialog = MultiEntryDialog(self.win, 'New Button', ['Text', 'Color', 'Command']) if not dialog.result[0]: print(dialog.result) new_button.destroy() return None if not dialog.result[2]: dialog.result[2] = '' name = uuid.uuid4() self.add_button(self.win, name, w, h, rx, ry, bg=dialog.result[1], bdw=0, command=dialog.result[2], text=dialog.result[0], image='') self.win.update() new_button.destroy() self.file_write( f'objects.append(["button", ["{name}", 0.03, 0.02,' f' {rx}, {ry}, "#282d36", 0, "pass", "{dialog.result[0]}' f'", ""]])\n') def file_write(self, to_write): self.file_result.write(to_write) def __init__(self, title='Windows Tool Kit Interface Creator', theme=None, background='white', style='default', logo_path=None, objects=None): self.theme = None basic = open('basic', 'r') self.file_result = open('result.py', 'w') self.file_result.write(basic.read() + '\nobjects = []\n') if objects is None: objects = [] self.win = ctk.CTk() if theme: try: self.update_theme(theme) except: raise RuntimeWarning(f'Theme {theme} doesn\'t exist') self.win.\ geometry(f'{infos.screen_size_x}x{infos.screen_size_y}') self.win.title(title) self.win.state('zoomed') self.win.iconbitmap(logo_path) self.win.configure(background=background) self.style = ttk.Style() self.style.theme_use(style) for _type, args in objects: if _type == 'frame': self.add_frame(self.win, args[0], args[1], args[2], args[3], args[4], args[5], args[6]) elif _type == 'button': self.add_button(self.win, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]) if logo_path: p1 = tk.PhotoImage(file=logo_path) self.win.iconphoto(False, p1) while True: try: self.win.winfo_exists() except: break self.win.update() App(background='dark gray', theme='Dark', style='vista', logo_path='logo.png', objects=[['frame', ['lbframe', 0.1, 1, 0, 0, '#2b2b2b', 0]], ['frame', ['rbframe', 0.1, 1, 0.9, 0, '#282d36', 0]], ['frame', ['cbar', 1, 0.03, 0, 0, '#2b2b2b', 0]], ['button', ['b1', 0.03, 0.02, 0.03, 0.05, '#282d36', 0, 'self.title', 'Change Title', '']], ['button', ['b1', 0.03, 0.02, 0.03, 0.08, '#282d36', 0, 'self.nbtn', 'Add Button', '']], ]) -
I don't know if this version of the code meets your definition of minimalist,
normally you can copy-paste it and it should work.
Thank you -
Hello,
Is it s supposed to work?
A minimalist code is a code of about ten or fifteen lines with
just what is needed to highlight the error
Moreover, you need to post the code using the tags as indicated
above:
https://codes-sources.commentcamarche.net/faq/11288-poster-un-extrait-de-code
Visually, it should look like this:
for k in range(10): print(k)
-
Hello Noa
I don't know if this version of the code meets your definition of minimalist,
It's better, but it's still not there. Basically, you need to remove all code blocks/functions that are not necessary to trigger your bug while keeping an executable program that can be run with just a copy-paste.
I also invite you to report the complete error (with the call stack), as it will help you identify which function crashed and where. You just need to keep all the sections of code that have been traversed so far to do a first cleanup. Then ideally, you should delete the sections of code that have been traversed and that do not play a role in triggering the issue.
The deleted code will then allow you to get rid of many imports (and for us, not having to install a bunch of modules that have nothing to do with the problem).
We can copy-paste it and it is supposed to work.
Being on Linux, I won't be able to reproduce your error because CreateDIBSection is a Windows function, which suggests that you are using a Python package specific to Windows.
According to this page, in C, it is possible to retrieve the last error.
According to this page, your bug might be due to outdated modules (try updating them).
I am also a bit skeptical about using customtkinter, where tkinter seems sufficient (why can't a tk.Image suffice where you create a ctk.CtkImage)? Try to explain to us, once your code is even more minimized, what you are trying to achieve.
Good luck