Как улучшить выбор размера окна в проекте tkinter, включая изображение кнопки в качестве метки? - PullRequest
0 голосов
/ 27 мая 2019

В настоящее время я работаю над небольшим проектом на python-3.x, включая некоторые ресурсы tkinter. Моя программа предназначена для отображения на экране списка изображений, включенных в каталог, каждое изображение помещается на кнопку, которая составляет шестую часть исходного изображения, и, если мы нажимаем на нее, она отображает изображение в его исходном размере на новое окно. Исходное окно задается количеством картинок, которые я помещаю в столбцы (я могу выбрать в коде), и я создал полосу прокрутки, потому что мне нужно работать с большим количеством картинок.

Но вот моя проблема, она работает нормально, за исключением того, что если я изменяю размер окна, например уменьшаю его, кнопки не следуют, они просто исчезают за окном и с полосой прокрутки.

Я не особенно хорош в Python, поэтому мне было интересно, что, возможно, если бы мы работали как потоки, мы могли бы получить размер окна вживую, а затем, если размер окна ниже / выше, чем у наших столбцов кнопок, мы можем изменить его размер. и измените количество столбцов, затем перезагрузите страницу, но мне придется работать с несколькими изображениями, так что это займет много времени.

from tkinter import *
from tkinter.filedialog import *
from tkinter.messagebox import *
from PIL import Image, ImageTk
import tkinter as tk
import glob
import os
import cv2
import copy
import _thread
import time

folder = 'X:/users/Robin/data/dataset-valid/visu/*.jpg'  

a=glob.glob(folder)

fic = "../data/list.txt"

fichObj=open(fic,"w")

p = []

for f in a:
    fichObj.write(f+"\n")
fichObj.close()

class SuperPhoto(object):
        def __init__(self, photo , image):

                self.photo = photo
                temp = cv2.resize(image, (int((self.photo.width())/6) , int((self.photo.height())/6))) 
                red = temp[:,:,2].copy()
                blue = temp[:,:,0].copy()
                temp[:,:,0] = red
                temp[:,:,2] = blue
                temp = Image.fromarray(temp)
                self.miniature = ImageTk.PhotoImage(temp)

        def agrandir(self):
                Newfen=Toplevel() 
                Newfen.geometry("+60+60")
                #self.photo.resize((500,500))


                print(type(self.photo))
                label = Label(Newfen, image=self.photo, width=self.photo.width(), height=self.photo.height())
                label.image = self.photo # keep a reference!
                label.pack()


if os.path.exists (fic):     #os.path utile 
        count = len(open(fic).readlines())    
        print(count)
        #lin = open(fic).readlines()
        #print(lin)


class ScrollableCanvas(Frame):
     def __init__(self, parent, *args, **kw):
        Frame.__init__(self, parent, *args, **kw)

        canvas=Canvas(self,bg='#FFFFFF',width=300,height=300,scrollregion=(0,0,500,500))

        canvas.update_idletasks() 

        vbar=Scrollbar(self,orient=VERTICAL)
        vbar.pack(side=RIGHT, fill=Y)
        vbar.config(command=canvas.yview)

        canvas.config(width=1200,height=700)
        canvas.config(yscrollcommand=vbar.set)
        canvas.pack(side=LEFT,expand=True,fill=BOTH)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = Frame(canvas)
        interior_id = canvas.create_window(0, 0, window=interior, anchor=NW )

        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            canvas.config(scrollregion="0 0 %s %s" % size)
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the canvas's width to fit the inner frame
                canvas.config(width=interior.winfo_reqwidth())
        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != canvas.winfo_width():
                # update the inner frame's width to fill the canvas
                canvas.itemconfigure(interior_id, width=canvas.winfo_width())
        canvas.bind('<Configure>', _configure_canvas)

class Main_frame(Frame):
    # Init
    def __init__(self, fenetre_principale=None):
        Frame.__init__(self, fenetre_principale)
        self.grid()
        self.scrollable_canvas = ScrollableCanvas(self)
        self.scrollable_canvas.grid(row=1,column=1)         

        nbCol = 4

        for file in a:
                image = Image.open(file)
                photo = ImageTk.PhotoImage(image)
                w = photo.width()
                L.append(int(w/6))
                #print(L)
                sumL = int(sum(L)/nbCol)

                print(sumL)

                p.append(SuperPhoto(photo, cv2.imread(file)))

        for ligne in range(int(count/nbCol)):
                for colonne in range(nbCol):
                        photo = p[ligne * nbCol + colonne]    
                        button = Button(self.scrollable_canvas.interior, image=photo.miniature, command=photo.agrandir)
                        button.grid(row=ligne, column=colonne)


if __name__ == "__main__":
    root = Tk()
    root.title("VISU")
    root.geometry("+0+0")
    L= []    


    interface = Main_frame(fenetre_principale=root)
    root.update_idletasks() 
    print(root.winfo_width())
    print(root.geometry())
    interface.mainloop()

Итак, я исключаю эту программу, которая работает как классический каталог, с колонками, которые изменяются автоматически при изменении размера окна, и с полосой прокрутки, которая следует за ней.

Если у вас есть какие-либо решения, это действительно поможет мне ..

Вы можете попробовать это, просто поместите несколько изображений jpeg в каталог и измените переменную папки с помощью ссылки вашего каталога.

Заранее благодарю за помощь, если у вас есть какие-либо вопросы, чтобы лучше понять, что я сказал, не стесняйтесь.

1 Ответ

0 голосов
/ 27 мая 2019

Каждый раз, когда размер окна root изменяется, запускается событие <Configure>. Поймай это следующим образом:

def resize(event):
    root.update_idletasks()
    #update all image sizes here if needed
    #all widgets can be 're-grided' here based on new width and height of root window

root.bind('<Configure>', resize)

Если вы хотите убедиться, что размер вашего окна не может быть изменен, используйте следующее:

root.resizable(False, False)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...