Уведомления

Группа в Telegram: @pythonsu

#1 Май 24, 2014 12:48:33

tisul
Зарегистрирован: 2014-01-06
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

Здравствуйте! Прошу помощи по следующей проблеме приведу код в общих чертах
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 ) поднимается вверх и при отображении виджета ее невидно получается таблицу с данными видно а шапку нет??? подскажите в каком направлении идти
создавать шапку в отдельном фрейме или есть другой путь решения данной проблемы???


Офлайн

#2 Май 24, 2014 13:01:30

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

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

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

from tkinter import *

P.S.S. master можно не указывать. Можно просто передавать виджет-родитель первым элементом и все

Офлайн

#3 Май 24, 2014 13:42:26

tisul
Зарегистрирован: 2014-01-06
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

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

Офлайн

#4 Май 24, 2014 20:29:38

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

tisul
Я хочу написать виджет-my_grid который легко можно встраивать в любой другой виджет и передавать ему данные из базы данных

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

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

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

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

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

P.S. Будут вопросы - пишите…

Офлайн

#5 Май 26, 2014 19:22:33

tisul
Зарегистрирован: 2014-01-06
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

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

Таблица размер 600 на 600 - основной виджет? в который вложена таблица 400 на 400? есть ли способ быстрого и точного определения размера 400 на 400 или его придется вычислять опираясь на размеры основного виджета от его размеров отнимать размер шапки и размеры скроллов?

Офлайн

#6 Май 27, 2014 12:50:24

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

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

Каким менеджером Вы пользуетесь. Я подскажу.

Офлайн

#7 Май 27, 2014 20:40:49

tisul
Зарегистрирован: 2014-01-06
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

пример ниже приведен чтобы можно было понять что я делаю(действительный код очень длинный думаю в нем разбираться не очень охота будет)
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.


Офлайн

#8 Май 27, 2014 21:47:58

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

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

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

P.S.

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

А вот это лучше показать. Чаще всего это делается неверно

Отредактировано 4kpt_II (Май 27, 2014 21:50:22)

Офлайн

#9 Май 28, 2014 09:28:52

tisul
Зарегистрирован: 2014-01-06
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

Картинки выложил на кибер диск в 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()

Отредактировано tisul (Май 28, 2014 09:48:09)

Офлайн

#10 Май 28, 2014 10:43:08

4kpt_II
От: Харьков
Зарегистрирован: 2013-10-24
Сообщения: 999
Репутация: +  58  -
Профиль   Отправить e-mail  

tkinter Canvas Scrollbar

Не могу нормально протестить.
Дайте результат метода

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

для примера.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version