Найти - Пользователи
Полная версия: tkinter Canvas Scrollbar
Начало » GUI » tkinter Canvas Scrollbar
1 2 3
tisul
Здравствуйте! Прошу помощи по следующей проблеме приведу код в общих чертах
root = Frame()
root.pack()
canvas = Canvas(master = root)
frame_grid = Frame(master = canvas)
в frame_grid создаю таблицу c помощью компоновщика grid(), в строке с индексом 0 размещаю заголовок таблицы

scrollbar = Scrollbar(master=root)
scrollbar(scrollregion = (0,21,100,200) - задаю scroll со второй frame_grid строки до последней

в результате шапка таблицы(строка с индексом 0 ) поднимается вверх и при отображении виджета ее невидно получается таблицу с данными видно а шапку нет??? подскажите в каком направлении идти
создавать шапку в отдельном фрейме или есть другой путь решения данной проблемы???


4kpt_II
Фреймов нагородили. Жуть root - не фрейм!!! Лучше так не делать.
Я посоветовал бы просто шапку расположить выше canvas по центру. И все. Она прокручиваться не будет. Это самый наитивный и простой способ. Да и выглядеть код будет нормально и красиво.
Есть еще способ с использование create_window, но вышеприведенный проще в разы и понятнее.

P.S. Никогда не делайте!!!

from tkinter import *

P.S.S. master можно не указывать. Можно просто передавать виджет-родитель первым элементом и все
tisul
4kpt_II
Фреймов нагородили. Жуть root - не фрейм!!! Лучше так не делать.Я посоветовал бы просто шапку расположить выше canvas по центру. И все. Она прокручиваться не будет. Это самый наитивный и простой способ. Да и выглядеть код будет нормально и красиво.Есть еще способ с использование create_window, но вышеприведенный проще в разы и понятнее.P.S. Никогда не делайте!!!
Я хочу написать виджет-my_grid который легко можно встраивать в любой другой виджет и передавать ему данные из базы данных. Поэтому я использую за основу Фрейм к которому прикрепляю скролы и canvas сам grid думаю переписать и реализовать непосредственно в canvas - вроде теперь уже понятно как это сделать, а шапку как вы предлагаете делать буду выше canvas но опять получается надо использовать Frame?! Если есть более продвинутые решения буду благодарен если поделитесь опытом!
4kpt_II
tisul
Я хочу написать виджет-my_grid который легко можно встраивать в любой другой виджет и передавать ему данные из базы данных

Простите, но вообще не понял.

tisul
Поэтому я использую за основу Фрейм к которому прикрепляю скролы и canvas сам grid думаю переписать и реализовать непосредственно в canvas

grid имеется ввиду менеджер геометрии?

Если все верно, тогда grid и запакуйте.
Получается следующее решение:

Так как Вы не используете ООП, то сверху базовым виджетом является root.
На нем любым из менеджеров геометрии (grid, place, pack) размещаются два виджета. Вверху - Label с названием таблицы. Внизу: canvas с create_window. А внтури create_window уже идет рамочка со всеми нужными вам объектами… Будь то помесь кнопок и полей ввода. Или вообще одни поля ввода (как в электронной таблице). Все, что угодно.

P.S. Будут вопросы - пишите…
tisul
Наконец то я смог сделать скроллируемую таблицу с шапкой по “x” и “у” но есть вопрос
как определить высоту и ширину видимой таблицы при уменьшении основного виджета.

Таблица размер 600 на 600 - основной виджет? в который вложена таблица 400 на 400? есть ли способ быстрого и точного определения размера 400 на 400 или его придется вычислять опираясь на размеры основного виджета от его размеров отнимать размер шапки и размеры скроллов?
4kpt_II
Размер определять не обязательно.
Для этого у менеджеров геометрии есть свойство, которое описывает растягивание вложенного объекта по горизонтали и вертикали. У каждого менеджера это свойство свое. Не его только у менеджера place. Но там заложен механизм относительных величин.

Каким менеджером Вы пользуетесь. Я подскажу.
tisul
пример ниже приведен чтобы можно было понять что я делаю(действительный код очень длинный думаю в нем разбираться не очень охота будет)
fr = Frame()
scr_y = tk.Scrollbar(fr,orient='vertical')
scr_x = tk.Scrollbar(fr,orient='horizontal')

canvas_header = Canvas(fr)
canvas_body = Canvas(fr)

scr_y.pack()
scr_x.pack()
canvas_header.pack()
canvas_body.pack()

в canvas_header размещаю шапку таблицы, строю менеджером grid
в canvas_body размещаю тело таблицы, строю менеджером grid

при уменьшении размеров fr мне нужно вычислить видимую область canvas_body

в таблице я сделал при нажатии клавиш управления “вверх” и “вниз” подсвечивание строк (переход по строкам) и когда я дохожу до последней видимой строки мне необходимо поднять таблицу вверх, чтобы увидеть следующую строку, для этого я и хочу знать видимую область canvas_body, зная ее я могу разделить высоту видимой области на высоту строки таблицы, тем самым я могу отследить когда необходимо поднимать или опускать таблицу. Вообще я все это дело реализую при помощи ООП, но код пишу кратко чтобы была ясна суть. За помощь благодарен очень - 4kpt_II.


4kpt_II
Давайте начнем с самого начала.
1. Что у Вас внутри второго Canvas? Тело таблицы состоит из чего? Если это списки (Listbox), то это одно дело, если это поля ввода Entry, то вообще другое.
2. Зачем для подписи использовать Canvas, если можно было просто Label?
3. Что в итоге хотите получить? Для большего понимания желательно скинуть скрин.

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

P.S.

tisul
при помощи ООП

А вот это лучше показать. Чаще всего это делается неверно
tisul
Картинки выложил на кибер диск в zip иначе не хочет их загружать
Your text to link here…
import tkinter as tk
import connectiondatabase as con
class Grid_Frame(tk.Frame):
    def __init__(self,master=None,cnf={},**kw):
        tk.Frame.__init__(self,master,cnf,**kw)
        self.propagate(flag=False)
        
        self.canvas_header = tk.Canvas(self,bg = 'blue')
        self.canvas_body = tk.Canvas(self,bg = 'green')
        self.canvas_body.bind_all("<MouseWheel>", self._on_mousewheel)
        
        self.frame_header = tk.Frame(self.canvas_header)
        self.frame_body = tk.Frame(self.canvas_body,bg = 'red')
        
        self.count = 0
        self.select_row = 0
        self.bind_all('<KeyPress>',self.key_press)
        self.coordinates_header = (0,0,0,0)
        
        self.list_header = [] # список заголовков таблицы, элементы списка словари, где ключ visible отображать заголовок name имя заголовка
        self.list_header = [{'id':'id','name':'код','visible':True,'width':25,'bg':'white','height':1,'anchor':'center'},
                            {'id':'name','name':'Наименование','visible':True,'width':50,'bg':'white','height':1,'anchor':'center'}]
        
        self.dict_column = {'id':0,'name':1}
        
    def create_grid(self,connection):
        scr_y = tk.Scrollbar(self,orient='vertical')
        scr_x = tk.Scrollbar(self,orient='horizontal')
        scr_y.pack(side='right',fill='y')
        scr_x.pack(side='bottom',fill='x')
        
        self.canvas_header.pack(fill='x',side='top')
        self.frame_header.pack(fill='x',side='top')
        
        self.canvas_body.pack(expand='yes',fill='both',side='top')
        self.frame_body.pack(fill='x',side='top',anchor='center')
        
        self.canvas_body.configure(yscrollcommand=scr_y.set)
        self.canvas_header.configure(xscrollcommand=scr_x.set)
        scr_y.configure(command=self.canvas_body.yview)
        scr_x.configure(command=self._xview)
        
        self.create_header(self.list_header) # создаем шапку таблицы
        self.fill_grid(connection) # заполняем таблицу
        
    def _xview(self,*arg):
        if arg[0] == 'scroll':
            self.canvas_body.xview_scroll(arg[1], arg[2])
            self.canvas_header.xview_scroll(arg[1], arg[2])
        elif arg[0] == 'moveto':
            self.canvas_body.xview_moveto(arg[1])
            self.canvas_header.xview_moveto(arg[1])
        
    def _on_mousewheel(self,event):
        self.canvas_body.yview_scroll(-1*int(event.delta/120), "units")#???????
    def create_header(self,list_header):
        column = 0
        for field in list_header:
            if field['visible']!=True:
                continue
            lb = tk.Label(self.frame_header,text=field['name'],relief='raised',width=field['width']
                       ,bg=field['bg'],height=field['height'])
            lb.grid(row=0,column=column,sticky='nsew')
            column +=1
        self.update()
        self.canvas_header.create_window(0,0,anchor='nw',window=self.frame_header,tag='header')
        
        coordinates_header = self.canvas_header.bbox('all')
        self.canvas_header.config(scrollregion=coordinates_header,height=coordinates_header[3])
                
    def fill_grid(self,connection):
        column = 0
        connection.cursor.execute("select id,name from proba")
        for k in cn.cursor:
            self.list_grid.append([])
            self.count +=1
            for key_column in self.dict_column:
                index_column = self.dict_column[key_column]
                lb = tk.Label(self.frame_body,text=k[index_column],relief='raised',anchor='w'
                           ,width=self.list_header[index_column]['width']
                           ,height = self.list_header[index_column]['height'])
                lb.grid(row=self.count,column=index_column,sticky='nsew')
                self.list_grid[self.count].append(lb)
        self.update()    
        self.canvas_body.create_window(0,0,anchor='nw',window=self.frame_body,tag='header')
                
        coordinates_scrollregion = self.canvas_body.bbox('all')
        self.canvas_body.config(scrollregion=coordinates_scrollregion,height=coordinates_scrollregion[3])
    
    def key_press(self,event):
        count = range(0,len(self.dict_column))#количество столбцов
        if event.keycode == 40:#клавиша управления вниз
            if self.select_row < self.count:
                if self.select_row>0 and self.select_row<self.count:
                    for index_count in count:
                        self.list_grid[self.select_row][index_count].configure(bg='white')
                self.select_row +=1
                for index_count in count:
                    self.list_grid[self.select_row][index_count].configure(bg='#8080c0')
        elif event.keycode == 38:# клавиша управления вверх
            if self.select_row >1:
                if self.select_row >1 :
                    for index_count in count:
                        self.list_grid[self.select_row][index_count].configure(bg='white')
                        
                self.select_row -=1
                for index_count in count:
                    self.list_grid[self.select_row][index_count].configure(bg='#8080c0')
#====================================================
if __name__ == '__main__':
    fr_grid = Grid_Frame(bg='blue',width=600,height=200)
    fr_grid.pack(expand='yes',fill='both',side="left",anchor='ne')
    cn = con.ConnectionDataBase('base')
    cn.verify_connection()
    if cn.flag_connection:
        fr_grid.create_grid(cn)
    tk.mainloop()
4kpt_II
Не могу нормально протестить.
Дайте результат метода

connection.cursor.execute("select id,name from proba")

для примера.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB