Scrollbars nur ein eine Listbox?

Fragen zu Tkinter.
Antworten
borgus
User
Beiträge: 11
Registriert: Donnerstag 18. September 2008, 13:08
Wohnort: Bremen

Donnerstag 18. September 2008, 13:17

Hi! Bin ganz neu hier und brauch' mal eure Hilfe... :)

Ich programmier' ein Fenster, indem oben eine Listbox ist und darunter ein paar
Köpfe...
Alle ist fein, aber: ich möchte eine scroll bar (x,y) in die Listbox setzen.
Das funktioniert auch ganz gut: aber die scrollbar ist nur auf der Höhe der Könpfe darunter und hat irgendwie nichts mit der listbox zu tun- das ist blöd :o(

Hab's bisher so gemacht:

in meiner klasse:

self.myList = tk.Listbox(master,selectmode=SINGLE, width=100)
self.scrollY = tk.Scrollbar(master, orient=tk.VERTICAL, command=self.myList.yview)
self.scrollX = tk.Scrollbar(master, orient=tk.HORIZONTAL, command=self.myList.xview)


self.myList.configure(yscrollcommand=self.scrollY.set)
self.myList.configure(xscrollcommand=self.scrollX.set)

self.myList.pack(fill=X)
self.scrollY.pack( side=RIGHT, fill=Y)
self.scrollX.pack( side=BOTTOM, fill=X)

kann mir jemand helfen? irgendwie bekomm' ich den dreh gerade nicht..

Thx!
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Donnerstag 18. September 2008, 17:00

Ich mache so etwas immer mit 'grid()':

Code: Alles auswählen

import Tkinter as tk


class Scrollbox(object):

  def __init__(self, master):
    
    self.myList = tk.Listbox(master,selectmode=tk.SINGLE, width=100)
    self.scrollY = tk.Scrollbar(master, orient=tk.VERTICAL, command=self.myList.yview)
    self.scrollX = tk.Scrollbar(master, orient=tk.HORIZONTAL, command=self.myList.xview)


    self.myList.configure(yscrollcommand=self.scrollY.set)
    self.myList.configure(xscrollcommand=self.scrollX.set)

    self.myList.grid(row=0, column=0, sticky=tk.N+tk.S+tk.W+tk.E)
    self.scrollY.grid(row=0, column=1, sticky=tk.N+tk.S)
    self.scrollX.grid(row=1, column=0, sticky=tk.E+tk.W)

    self.fill_it(100)


  def fill_it(self, n):

    for i in range(1, n):

      self.myList.insert(tk.END, '---'.join([str(i)] * i))

      
    
root = tk.Tk()
s = Scrollbox(root)
root.mainloop()
Hoffe, es hilft ein wenig.

:wink:
yipyip
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Donnerstag 18. September 2008, 20:05

Mit dem pack()-Manager z.B. so:

Code: Alles auswählen

import Tkinter as tk
from random import randrange

root = tk.Tk()
scroller = tk.Scrollbar(root)
listbox = tk.Listbox(root,yscrollcommand=scroller.set)
listbox.pack(side=tk.LEFT)
scroller.config(command=listbox.yview)
scroller.pack(side=tk.LEFT,fill=tk.Y)
for k in range(50):
    listbox.insert("end","".join([chr(randrange(65,91)) for p in range(15)]))
root.mainloop()
borgus
User
Beiträge: 11
Registriert: Donnerstag 18. September 2008, 13:08
Wohnort: Bremen

Freitag 19. September 2008, 09:27

Schonmal danke für eure Antworten!
Das Problem ist irgendwie die Platzierung, weil die Scrollbar ja voll auf
die Liste reagiert und ich mich mit der Scrollbar durch die Liste bewegen
kann. Es sieht bei mir nur so aus:

Bild

Ich hab' mich bisher nicht um die Platzierung der Button gekümmert, weil
ich erstmal die Funktionalität herstellen wollte, aber die Scrollbar sollte irgendwie
schon in der Liste sein...
Weiß jetzt irgendwie nicht, wie ich das ding expliziet dort hineinstecke :(
Benutzeravatar
wuf
User
Beiträge: 1418
Registriert: Sonntag 8. Juni 2003, 09:50

Freitag 19. September 2008, 11:12

Hallo borgus

Damit wir dir helfen können musst du uns unbeding deinen Projekt- Code zur schau stellen.

Gruss wuf :wink:
Take it easy Mates!
borgus
User
Beiträge: 11
Registriert: Donnerstag 18. September 2008, 13:08
Wohnort: Bremen

Freitag 19. September 2008, 11:55

jupp, hier läuft alles ab:

class App:
def __init__(self, master):
self.jM = jobManager()
self.entryCount = 0
self.listSelection = -1


self.scrollY = tk.Scrollbar(master, orient=tk.VERTICAL)
self.scrollX = tk.Scrollbar(master, orient=tk.HORIZONTAL)
self.myList = tk.Listbox(master,selectmode=SINGLE, width=100, yscrollcommand=self.scrollY)
self.scrollY.config(command=self.myList.yview)
self.myList.configure(yscrollcommand=self.scrollY.set)
self.myList.configure(xscrollcommand=self.scrollX.set)

self.myList.pack(fill=X)
self.scrollY.pack( side=RIGHT, fill=Y)
self.scrollX.pack( side=BOTTOM, fill=X)

#add all the buttons
self.addBut = tk.Button(master, text='add')
self.removeBut = tk.Button(master, text='remove')
self.openFiles = tk.Button(master, text='add from dialog')
self.lbl = tk.Label(master, text='enter frame-range')
self.rangeInput = tk.Entry(master)
self.downBut = tk.Button(master, text='down')
self.upBut = tk.Button(master, text='up')
self.jmReport = tk.Button(master, text='check jobManager')

#make buttons visible

self.downBut.pack()
self.upBut.pack()
self.lbl.pack(fill=X)
self.pathInput.pack(fill=X)
self.openFiles.pack(fill=X)
self.addBut.pack(fill=X)
self.removeBut.pack(fill=X)
self.jmReport.pack(fill=X)

#set focus on textfield
self.pathInput.focus_set()
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Freitag 19. September 2008, 12:44

1. Bitte verwende doch künftig die Code-Tags für den Code. Das liest sich besser.

2. Die import-Anweisung für Tkinter fehlt. Aus dem Code lässt sich erschließen, dass du wohl mittels

Code: Alles auswählen

import Tkinter as tk
importiert hast.

Dann funktionieren die Konstanten RIGHT, BOTTOM, X etc. aber nicht. Es sind ja Tkinter-Konstanten, und du musst sie wie bei "tk.VERTICAL" aufrufen.

Da du aber anscheinend keinen NameError bekommst, hast du Tkinter offenbar zusätzlich nochmal über

Code: Alles auswählen

from Tkinter import *
eingebunden. Das solltest du nicht tun.

Allerdings erklärt das nicht das von dir nicht gewünschte Aussehen der GUI.

Mein Vorschlag wäre: Lies dich mal in den pack()-Manager ein. Z.B. hier:
http://www.ferg.org/thinking_in_tkinter ... grams.html

Den Sternchenimport solltest du von dort aber nicht übernehmen.
borgus
User
Beiträge: 11
Registriert: Donnerstag 18. September 2008, 13:08
Wohnort: Bremen

Freitag 19. September 2008, 13:07

danke für den link numerix, sollte mich damit erstmal beschäftigen...

sorry, hatte die importanweisung nicht mitkopiert:

Code: Alles auswählen


import Tkinter as tk
from string import split
from Tkconstants import *
from tkFileDialog import askopenfilenames
hab' schon festgestellt das importieren mit * nicht ganz so toll ist - baue gerade den code um.
hab nur den konstruktor geposted, weil dort wahrscheinlich die fehlerquelle ist.

gruß!
Benutzeravatar
wuf
User
Beiträge: 1418
Registriert: Sonntag 8. Juni 2003, 09:50

Freitag 19. September 2008, 20:07

Hallo borgus

Hier habe ich deine Applikation einmal mit dem Einsatz des Tkinter Pack-Layout Managers gelöst. Eine kleine Vorwarnung. Beim Einsatz des Pack-Managers braucht es ein wenig die Fähigkeiten eines Magiers! :D
Man muss ein wenig herumspielen mit den Pack-Optionen 'side', 'fill', 'expand', 'padx', 'pady', damit sich das ganze beim ändern der Fenstergrösse durch ziehen oder mit den Maximier- bzw. Minimier-Fensterschaltflächen dynamisch richtig verhält.
Wenn du mit dem Pack-Manager arbeitest, verwende möglichst viele Frame-Widgets. Ich würde zuerst mit der Planung des ganzen Frame-Work beginnen vor der direkten Platzierung der Bedienungs bzw. Ein- Ausgabe-Widgets. Die Reihenfolge im Skript spielt auch eine Rolle.

Hier mein Code-Snippet zum herum experimentieren.

[Code ausgelagert]

Viel Vergnügen mit Python & Tkinter

N.B. Habe das Snippet mit Python2.5 unter Linux SuSE 10.0 ausgetestet. Eventuell kann es unter Windows kleine Abweichungen geben

Korrektur: Auf Zeile 68 hat sich ein kleiner Fehler eingeschlichen!

Code: Alles auswählen

        #~~ Erstelle die X-Ziehleiste
        self.scroll_x = tk.Scrollbar(self.b_container, orient=tk.HORIZONTAL,
            bd=1, command=self.my_list.xview)
        self.scroll_x.pack(side=tk.LEFT, fill=tk.X, expand=tk.YES)
Gruss wuf :wink:
Take it easy Mates!
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Freitag 19. September 2008, 23:04

Ich verstehe einfach nicht, was Ihr gegen
den Grid-Packer habt. :wink:
Der erspart doch die Fummelei mit den
extra-Frames für die X-, Y-Scrollbar
und die Eckbox.

Code: Alles auswählen

#!usr/bin/env python

####

import Tkinter as tk

####

class Scrollbox(object):

  def __init__(self, root):

    self.root = root
    self.sb_frame = tk.Frame(self.root)
    
    self.mylist = tk.Listbox(self.sb_frame,selectmode=tk.SINGLE,
                             bg='#ffffdd')
    self.y_scroller = tk.Scrollbar(self.sb_frame, orient=tk.VERTICAL,
                                   command=self.mylist.yview)
    self.x_scroller = tk.Scrollbar(self.sb_frame, orient=tk.HORIZONTAL,
                                   command=self.mylist.xview)

    self.mylist.configure(yscrollcommand=self.y_scroller.set)
    self.mylist.configure(xscrollcommand=self.x_scroller.set)

    self.mylist.grid(row=0, column=0,
                     sticky=tk.N+tk.S+tk.W+tk.E)
    self.y_scroller.grid(row=0, column=1,
                         sticky=tk.N+tk.S)
    self.x_scroller.grid(row=1, column=0,
                         sticky=tk.E+tk.W)
    
    self.sb_frame.grid_columnconfigure(0, weight=1)
    self.sb_frame.grid_rowconfigure(0, weight=1)

    self.fill_it(100)
    self.sb_frame.pack(fill=tk.BOTH, expand=tk.YES)
    
    tp_frame = self.make_textpath(self.root,'Text Path')
    but_frame = self.make_buttons(self.root, 'Add', 'Remove',
                                  'Add from Dialog',
                                  'Up', 'Down')

    but_frame.pack(side=tk.BOTTOM, fill=tk.X, expand=tk.YES)
    tp_frame.pack(side=tk.BOTTOM, fill=tk.X, expand=tk.YES)

    
  def make_textpath(self, master, text):

    frame = tk.Frame(master)
    self.tp_label = tk.Label(frame, text=text)
    self.tp_entry = tk.Entry(frame, bg='white')

    self.tp_label.pack(side=tk.LEFT, fill=tk.X,
                       padx=4) 
    self.tp_entry.pack(side=tk.RIGHT, fill=tk.X,
                       padx=4, expand=tk.YES)
    
    return frame


  def make_buttons(self, master, *texts):

    frame = tk.Frame(master)
    self.buttons = [tk.Button(frame, text=txt) for txt in texts] 

    for i, but in enumerate(self.buttons):
      but.grid(row=0, column=i, sticky=tk.W+tk.E)
      frame.grid_columnconfigure(i, weight=1)
      
    return frame

  
  def fill_it(self, n):

    for i in range(1, n):
      self.mylist.insert(tk.END, '---'.join([str(i)] * i))

####
      
def main_scroller():

  root = tk.Tk()
  s = Scrollbox(root)
  root.mainloop()
  
####      

if __name__ == '__main__':

  main_scroller()
  
####
@wuf
Welch' Ehre, meine 'fill_it()'-Methode in Deinem Programm sehen zu dürfen.

:wink: :wink:
yipyip
Benutzeravatar
wuf
User
Beiträge: 1418
Registriert: Sonntag 8. Juni 2003, 09:50

Samstag 20. September 2008, 00:01

Hallo yipyip

Habe absolut nichts gegen den Tkinter Grid-Layout-Manger. Setze ihn von Zeit zu Zeit auch ein. Speziell die 'widget.grid_remove()' und 'widget.grid() Methoden finde ich sehr nützlich was beim Pack-Manager aufwendiger zu realisieren ist damit ein entferntes Widget-Objekt auch wirklich wieder am richtigen Ort eingesetzt werden kann. Übrigens basiert das geniale Pmw-Package fast durchgehend auf dem Grid-Manager.

Finde es gut, dass du hier auch noch die Grid-Variante vorgestellt hast, so kann 'borgus' mit beiden Varianten auseinandersetzen.

Gruss wuf :wink:
Take it easy Mates!
Antworten