Fortschrittsbalken mit Canvas-Widget ?

Fragen zu Tkinter.
Antworten
abgdf

Hallo,

kaytecs News-Ticker

http://www.python-forum.de/topic-16349.html

find' ich ja klasse. Könnte man so ähnlich nicht auch einen Fortschrittsbalken mit dem Canvas-Widget bauen ?

Werd's bald mal probieren, wäre aber auch für Vorschläge dankbar.

Viele Grüße
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Ein Fortschrittsbalken dürfte sich einfacher realisieren lassen:
Ein Rechteck mit gleichbleibender Höhe und wachsender Breite zeichnen lassen.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo abgdf !

Helfe dir gerne, doch fuer was benoetigst du denn diesen Balken ?

gruss frank
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo abgdf

Unser Forummitglied 'dh233' hat schon einmal etwas in dieser Richtung präsentiert:

http://www.python-forum.de/topic-7205.html

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

@wuf

Das mit einem Fortschrittsbalken wollte ich auch mal machen, doch ich hatte so meine Probleme. Ich wollte den Wii-Controller initialisieren und dafuer solch einen Balken verwenden. Das Initialisieren blockiert die "After-Schleife" und somit auch die Oberflaeche. Mit einem Thread wuerde es bestimmt moeglich sein, doch dafuer bekomme ich immer eins auf die Ohren :oops:. Habe ich evt. ja auch falsch verstanden !?

gruss frank
abgdf

Hallo,

danke für den Hinweis ! Klappt schon ganz gut:

Code: Alles auswählen

#!/usr/bin/env python

import Tkinter
import tkMessageBox

class MainWindow:

    def __init__(self):

        self.mw = Tkinter.Tk()
        self.mw.geometry("+250+200")

        self.btn1 = Tkinter.Button(self.mw, text = "Start", command = self.incr)
        self.btn1.pack()

        self.pg = ProgressBar(self.mw)
        self.pval = 0
        self.pg.updateProgress(self.pval)

        self.btn2 = Tkinter.Button(self.mw, text = "Exit", command = self.mw.destroy)
        self.btn2.pack()

        self.mw.mainloop()

    def incr(self):

        if self.pval == 100:
            self.pval = 0
            tkMessageBox.showinfo(title = 'Fertig', message = "Fertig")
            self.pg.updateProgress(self.pval)
            return

        if self.pval < 100:
            self.pval += 1
            self.mw.after(100, self.incr)

        self.pg.updateProgress(self.pval)


class ProgressBar:

    def __init__(self, master, orientation = "horizontal",
                 min = 0, max = 100, width = 100, height = 18,
                 doLabel = 1, appearance = "sunken",
                 fillColor = "blue", background = "gray",
                 labelColor = "yellow", labelFont = "Verdana",
                 labelText = "", labelFormat = "%d%%",
                 value = 50, bd = 2):

        # preserve various values

        self.master = master
        self.orientation = orientation
        self.min = min
        self.max = max
        self.width = width
        self.height = height
        self.doLabel = doLabel
        self.fillColor = fillColor
        self.labelFont =  labelFont
        self.labelColor = labelColor
        self.background = background
        self.labelText = labelText
        self.labelFormat = labelFormat
        self.value = value

        self.frame = Tkinter.Frame(master, relief = appearance, bd = bd)
        self.frame.pack()
        self.canvas = Tkinter.Canvas(self.frame, height = height, width = width, bd = 0,
                           highlightthickness = 0, background = background)
        self.scale = self.canvas.create_rectangle(0, 0, width, height,
                                                fill = fillColor)
        self.label = self.canvas.create_text(self.canvas.winfo_reqwidth()/ 2,
                                           height / 2, text = labelText,
                                           anchor = "c", fill = labelColor,
                                           font = self.labelFont)
        self.update()
        self.canvas.pack(side = 'top', fill = 'x', expand = 'no')

    def updateProgress(self, newValue, newMax = None):

        if newMax:
            self.max = newMax
        self.value = newValue
        self.update()

    def update(self):
        # Trim the values to be between min and max
        value = self.value
        if value > self.max:
            value = self.max
        if value < self.min:
            value = self.min
        # Adjust the rectangle
        if self.orientation  ==  "horizontal":
            self.canvas.coords(self.scale, 0, 0,
              float(value) / self.max * self.width, self.height)
        else:
            self.canvas.coords(self.scale, 0,
                               self.height - (float(value) /
                                              self.max*self.height),
                               self.width, self.height)
        # Now update the colors

        self.canvas.itemconfig(self.scale, fill = self.fillColor)
        self.canvas.itemconfig(self.label, fill = self.labelColor)

        # And update the label

        if self.doLabel:
            if value:
                if value >=  0:
                    pvalue = int((float(value) / float(self.max)) *
                                   100.0)
                else:
                    pvalue = 0
                self.canvas.itemconfig(self.label, text = self.labelFormat
                                         % pvalue)
            else:
                self.canvas.itemconfig(self.label, text = '')
        else:
            self.canvas.itemconfig(self.label, text = self.labelFormat %
                                   self.labelText)
        self.canvas.update_idletasks()
       
       
if __name__ == "__main__":
   app = MainWindow()
Viele Grüße
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Das ist doch schon ganz nett geworden!

Ein paar kleinere Anmerkungen:

Die Methode incr() könnte man etwas kürzer halten. Statt eines zweiten "if" sollte ein "else" genügen; dann braucht man updateProgress() nur einmal aufzurufen und das "return" entfällt ebenfalls.

Die Schlüsselwortparameter, die bei der Instanzbildung einer ProgressBar übergeben werden können, sollte man vielleicht noch prüfen. So liefert z.B. eine ProgressBar mit "orientation='quer'" ebenfalls einen vertikalen Balken ...

Überlegen könnte man auch, ob man die Schriftgröße für die Fortschrittsanzeige vom Programm optimiert berechnen lässt. Die jetzige Fassung ermöglicht es z.B. via labelFont-Option auch Font-Objekte mit Übergröße festzulegen (etwa labelFont = ("Verdana",60,"bold")), die dann gar nicht mehr in den Fortschrittsbalken hineinpassen.

Die Schlüsselwortparameter min und max von ProgressBar solltest du umbenennen, weil dadurch die eingebauten Funktionen min/max überschattet werden.
Antworten