Почему не все изображения из папки отображаются на моем ярлыке tkinter в рамке на холсте? - PullRequest
1 голос
/ 28 октября 2019

Я пишу скрипт python tkinter для извлечения файлов .jpg из папки, созданной opencv, и горизонтального отображения их всех рядом друг с другом. Я могу заставить код работать, в котором он отображает JPG файлы рядом друг с другом. Однако через несколько кадров tkinter размещает один файл jpg над другим до последнего файла jpg. Не уверен, что я делаю не так. Ниже мой сценарий. Любое предложение приветствуется.

import os
import sys
from Tkinter import *
from PIL import Image, ImageTk
import tkFileDialog

path = 'C:\\JPEGs'
images = []

for dirname, dirnames, filenames in os.walk(path):
    for filename in filenames:
        file = os.path.join(dirname, filename)
        if '.jpg' in file.lower() :
            images.append(file)

images.sort(key=lambda f: int(filter(str.isdigit, f)))
#print images
## Main window
root = Tk()
root.geometry('1280x720')
root.title("VIDYOANALYSER-Sachin Chandrashekar")
root.wm_iconbitmap('ad1.ico')
## Grid sizing behavior in window
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
# Canvas
cnv = Canvas(root,bg="light yellow")
cnv.grid(row=0, column=0, sticky='nswe')

## Scrollbars for canvas
hScroll = Scrollbar(root, orient=HORIZONTAL, command=cnv.xview)
hScroll.grid(row=1, column=0, sticky='we')
vScroll = Scrollbar(root, orient=VERTICAL, command=cnv.yview)
vScroll.grid(row=0, column=1, sticky='ns')
cnv.configure(xscrollcommand=hScroll.set, yscrollcommand=vScroll.set)
# Frame in canvas
frm = Frame(root,bg="light yellow")


## This puts the frame in the canvas's scrollable zone
cnv.create_window(0, 0, window=frm, anchor='nw')
## Frame contents
columnCount=0

for files in images:
    im = Image.open(files)
    tkimage = ImageTk.PhotoImage(im)
    myvar=Label(frm,image = tkimage,text=str(os.path.basename(files).strip('.jpg')), compound=TOP,bg='sky blue',relief=SUNKEN)
    myvar.image = tkimage
    myvar.grid(row=0, column=columnCount, sticky='nswe')
    myvar.grid_rowconfigure(0, weight=1)
    myvar.grid_columnconfigure(0, weight=1)
    columnCount += 1



## Update display to get correct dimensions
frm.update_idletasks()
myvar.update_idletasks()
## Configure size of canvas's scrollable zone
cnv.configure(scrollregion=(0, 0, frm.winfo_width(), frm.winfo_height()))

## Go!
root.mainloop()

Ожидается: есть 253 файла JPEG, и я ожидаю, что все кадры будут отображаться. Проверьте ссылку - https://i.stack.imgur.com/BRMTy.png Фактически: отображаются только 243 файла, а остальные кадры отображаются поверх другого, и только последний кадр (наполовину обрезанный) виден в интерфейсе пользователя. Проверьте ссылку - https://i.stack.imgur.com/KqMeL.png

1 Ответ

1 голос
/ 28 октября 2019

Как @Jasonharper указал, что в этом случае tkinter использует 16-битные координаты. (не уверен, что это одинаково для всех контейнеров) .

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

Я добавил 2 переменные:

total_image_size = 0
total_widget_size = 0

Затем при создании всех виджетов я проверяю размер каждого изображения и обновляю total_image_size.

Затем я перебираю все виджетыв кадре, чтобы получить их ширину с помощью winfo_width() и обновить total_widget_size.

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

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

Мое тестовое изображение имеет ширину 82 пикселя, а виджет - 88 пикселей на изображение / виджет.

Заключение :

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

Я буду работать на exaСделайте это после полудня или завтра, поскольку у меня есть собрания весь день.

Результаты :

enter image description here

Код :

import os
import tkinter as tk
from PIL import Image, ImageTk


path = r'complete\file\path\here'
images = []
total_image_size = 0
total_widget_size = 0
for dirname, dirnames, filenames in os.walk(path):
    for filename in filenames:
        file = os.path.join(dirname, filename)
        images.append(file)

tk.Tcl().call('lsort', '-dict', images)

root = tk.Tk()
root.geometry('1280x720')
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
cnv = tk.Canvas(root,bg="light yellow")
cnv.grid(row=0, column=0, sticky='nswe')

hScroll = tk.Scrollbar(root, orient='horizontal', command=cnv.xview)
hScroll.grid(row=1, column=0, sticky='we')
vScroll = tk.Scrollbar(root, orient='vertical', command=cnv.yview)
vScroll.grid(row=0, column=1, sticky='ns')
cnv.configure(xscrollcommand=hScroll.set, yscrollcommand=vScroll.set)
frm = tk.Frame(root, bg="light yellow")
cnv.create_window(0, 0, window=frm, anchor='nw')
columnCount = 0

for files in images:
    im = Image.open(files)
    width, height = im.size
    total_image_size += width
    tkimage = ImageTk.PhotoImage(im)
    myvar = tk.Label(frm, image=tkimage, text=str(os.path.basename(files).strip('.jpg')),
                  compound='top', bg='sky blue', relief='sunken')
    myvar.image = tkimage
    myvar.grid(row=0, column=columnCount, sticky='nswe')
    myvar.grid_rowconfigure(0, weight=1)
    myvar.grid_columnconfigure(0, weight=1)
    columnCount += 1


frm.update_idletasks()
cnv.configure(scrollregion=(0, 0, frm.winfo_width(), frm.winfo_height()))


def do_thing():
    global total_widget_size
    for ndex, widget in enumerate(frm.winfo_children()):
        if ndex <= 371:  # set the last image to be loaded before stacking started.
            total_widget_size += widget.winfo_width()
    print('Total widget width prior to stacking', total_widget_size)


print('Total image width', total_image_size)
# short delay so we can check size after all images have been loaded.
# If it takes longer than 3 seconds for your app to load then change this time to be more.
root.after(3000, do_thing)
root.mainloop()

Используется тестовое изображение:

enter image description here

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