我正在粘貼我一直在為“條形圖”作業的所有代碼。如果有興趣,我可以提供我從中獲取的原始代碼。代碼運行良好并按預期生成圖表,但網格布局很奇怪。按鈕和標簽更新都在形狀笨拙的“空間”中。我的假設是主畫布區域占據了框架的大部分(視窗?),所以當其他小部件添加到網格時,它們會根據較大的畫布視窗放置。
有沒有辦法對正在進行繪圖的畫布框架/視窗進行子集化,這樣它就不會影響其他小部件的大小?或者有沒有更好的方法將所有東西放在一起?
如果我需要澄清任何事情,請告訴我。
謝謝!
編輯
這是 GUI 的影像。首先,主繪圖畫布在網格中(row=1,col=1)。當我將按鈕放在圖的右側時,它們位于同一行 = 1,但現在分別位于第 2 列和第 3 列。由于行高如此之大,按鈕被放置在該行的中心。在查看“Ch_A”和“Ch_B”標簽時,按鈕的列寬也會發生類似的情況。
理想情況下,我希望按鈕和相關的“頻道標簽”能夠整齊地排列在一起。有沒有最佳實踐方法來解決這個問題?

編輯
# (c) MIT License Copyright 2014 Ronald H Longo
# Please reuse, modify or distribute freely.
from collections import OrderedDict
import tkinter as tk
from tkinter import Label, ttk
# convert rate axis label to something useful and not too large...
def ratestr(f):
if (f >= 1e6):
return('{:.1f} MHz'.format(f/1000000.0))
elif (f >= 1e3):
return('{:.1f} kHz'.format(f/1000.0))
else:
return('{:.1f} Hz'.format(f))
class StripChart( tk.Frame ):
def __init__( self, parent, scale, historySize, trackColors, *args, **opts ):
# Initialize
super().__init__( parent, *args, **opts )
self._trackHist = OrderedDict() # Map: TrackName -> list of canvas objID
self._trackColor = trackColors # Map: Track Name -> color
#Set Scaling
self._chartHeight = scale 1
self._chartLength = historySize * 2 # Stretch for readability
self.max_x = self._chartLength
self.max_y = self._chartHeight -1
#Create main canvas
self._canvas = tk.Canvas( self, height=self._chartHeight 50,
width=self._chartLength, background='black' )
# self._canvas.grid( sticky=tk.N tk.S tk.E tk.W )
self._canvas.grid(row=1, column=1)
self._canvas.create_text(6,50,text="Total Counts")
#Labeling
self.Ch_A = Label(self)
self.Ch_A.grid(row=0, column=2)
self.Ch_B = Label(self)
self.Ch_B.grid(row=0, column=3)
self.Ch_C = Label(self)
self.Ch_C.grid(row=0, column=4)
self.Ch_D = Label(self)
self.Ch_D.grid(row=0, column=5)
self.channel_labels = [self.Ch_A, self.Ch_B, self.Ch_C, self.Ch_D]
# _y_label.grid(row=0, column=0)
# Draw horizontal to divide plot from tick labels
x, y = 0, self._chartHeight 2
x2, y2 = self._chartLength, y
self._baseLine = self._canvas.create_line( x, y, x2, y2, fill='white' )
# create axis labels
self.maxy = Label(self, text=ratestr(self.max_y), font=("Arial", 15), width=8)
self.maxy.grid(column=0,row=0)
self.midy = Label(self, text=ratestr(self.max_y/2), font=("Arial", 15), width=8)
self.midy.grid(column=0,row=1)
self.midx = Label(self, text="Seconds", font=("Arial", 15), width=6)
self.midx.grid(column=1,row=2)
# Init track def and histories lists
self._trackColor.update( { 'tick':'white', 'tickline':'white',
'ticklabel':'white' } )
for trackName in self._trackColor.keys():
self._trackHist[ trackName ] = [ None for x in range(historySize) ]
#Make stop button
self.Button1 = ttk.Button(master=self, text= "Quit", command=quit)
self.Button1.grid(row=1,column=2)
#Collect Data Button
self.Button2 = ttk.Button(self, text="Collect Data" )
self.Button2.grid(row=1, column=3)
def plotValues( self, **vals ):
row_val = 0
for trackName, trackHistory in self._trackHist.items():
self._canvas.delete( trackHistory.pop(0) )# Remove left-most canvas objs
self._canvas.move( trackName, -2, 0 )# Scroll canvas objs 2 pixels left
# Plot the new values
try:
val = vals[ trackName ]
x = self._chartLength
y = self._chartHeight - val #Makes random value maxy -> y=0
color = self._trackColor[ trackName ]
objId = self._canvas.create_line( x, y, x 1, y, fill=color,
width=3, tags=trackName )
trackHistory.append( objId )
row_val = 1
except:
trackHistory.append( None )
def makeLabels(self, **vals):
for x, l in zip(vals,self.channel_labels): #change your for loops to this
l.configure(text = x ": " str(vals[x]), fg=self._trackColor[x])
#l['text'] = x ": " str(vals[x])
# l.after(1,self.makeLabels(**vals))
def drawTick( self, text=None, **lineOpts ):
# draw vertical tick line
x = self._chartLength
y = 1
x2 = x
y2 = self._chartHeight
color = self._trackColor[ 'tickline' ]
objId = self._canvas.create_line( x, y, x2, y2, fill=color,
tags='tick', **lineOpts )
self._trackHist[ 'tickline' ].append( objId )
# draw tick label
if text is not None:
x = self._chartLength
y = self._chartHeight 10
color = self._trackColor[ 'ticklabel' ]
objId = self._canvas.create_text( x, y, text=text,
fill=color, tags='tick' )
self._trackHist[ 'ticklabel' ].append( objId )
def configTrackColors( self, **trackColors ):
# Change plotted data color
for trackName, colorName in trackColors.items( ):
self._canvas.itemconfigure( trackName, fill=colorName )
# Change settings so future data has the new color
self._trackColor.update( trackColors )
##########################
#
# MAIN PROGRAM
#
##########################
if __name__ == '__main__':
top = tk.Tk( )
# style = ttk.Style(top)
# style.theme_use('classic')
scale_max = 600
graph = StripChart( top, scale_max, 400, { 'Ch_A':'blue', 'Ch_B':'green', 'Ch_C':'red','Ch_D':'yellow' } )
graph.grid( )
val_A = 0
val_B = 0
val_C = 0
val_D = 0
delta = [ -4, -3, -2, -1, 0, 1, 2, 3, 4 ] # randomly vary the values by one of these
tickCount = 0
def nextVal( current, lowerBound, upperBound ):
from random import choice
current = choice( delta )
if current < lowerBound:
return lowerBound
elif current > upperBound:
return upperBound
else:
return current
def plotNextVals( ): #Main function
global val_A, val_B, val_C, val_D, tickCount
if tickCount % 50 == 0:
graph.drawTick( text=str(tickCount), dash=(1,4) )
graph.makeLabels(Ch_A=val_A, Ch_B=val_B, Ch_C=val_C, Ch_D=val_D )
tickCount = 1
val_A = nextVal( val_A, 0, scale_max )
val_B = nextVal( val_B, 0, scale_max )
val_C = nextVal( val_C, 0, scale_max )
val_D = nextVal( val_D, 0, scale_max )
graph.plotValues( Ch_A=val_A, Ch_B=val_B, Ch_C=val_C, Ch_D=val_D )
changeColor = { 800: 'black',
1200: 'yellow',
1600: 'orange',
2000: 'white',
2400: 'brown',
2800: 'blue' }
if tickCount in changeColor:
graph.configTrackColors( A=changeColor[tickCount] )
top.after( 250, plotNextVals )#Repeats after 1000 ms
top.after( 100, plotNextVals )
top.mainloop( )
uj5u.com熱心網友回復:
如果使用,grid(..., sticky="N")則將元素移動到頂部邊框 ( North)
#Make stop button
self.Button1 = ttk.Button(self, text= "Quit", command=quit)
self.Button1.grid(row=1, column=2, sticky='N')
#Collect Data Button
self.Button2 = ttk.Button(self, text="Collect Data" )
self.Button2.grid(row=1, column=3, sticky='N')

但是按鈕與 位于同一列Ch_A,Ch_B因此列中的兩個元素具有相同的寬度。您可以將按鈕或標簽Frame放入網格中,并使用此框架將這個框架放入網格中columnspan=4(按鈕不會改變標簽的寬度
self.frame_buttons = tk.Frame(self)
self.frame_buttons.grid(row=1, column=2, sticky='N', columnspan=4)
#Make stop button
self.Button1 = ttk.Button(self.frame_buttons, text= "Quit", command=quit)
self.Button1.grid(row=1, column=1)
#Collect Data Button
self.Button2 = ttk.Button(self.frame_buttons, text="Collect Data" )
self.Button2.grid(row=1, column=2)

此時Ch_A,Ch_B不要依賴按鈕。因為框架使用columnspan=4所以它使用 4 列的寬度,并以該寬度為中心。框架不使用全寬 - 左側和右側都有可用空間。
如果我使用,sticky='NEW'那么框架將使用全寬,但按鈕(或列)將不使用此空間。我red在框架中添加了背景來顯示它。
self.frame_buttons = tk.Frame(self, bg='red')
self.frame_buttons.grid(row=1, column=2, sticky='NEW', columnspan=4)

如果我使用,.columnconfigure(..., weight=1)那么我可以重用現有列中的可用空間。
self.frame_buttons = tk.Frame(self, bg='red')
self.frame_buttons.grid(row=1, column=2, sticky='NEW', columnspan=4)
self.frame_buttons.columnconfigure(1, weight=1)
self.frame_buttons.columnconfigure(2, weight=1)

weightis 的總和2和第一列的權重 = 1,因此它使用1/2可用空間,第二行使用相同的空間。但是我可以使用更大的值weight以不同的方式分割可用空間。
如果我sticky='WE'用于按鈕,則按鈕將在列中使用全尺寸。這樣按鈕將具有相同的寬度
self.frame_buttons = tk.Frame(self, bg='red')
self.frame_buttons.grid(row=1, column=2, sticky='NEW', columnspan=4)
self.frame_buttons.columnconfigure(1, weight=1)
self.frame_buttons.columnconfigure(2, weight=1)
#Make stop button
self.Button1 = ttk.Button(self.frame_buttons, text= "Quit", command=quit)
self.Button1.grid(row=1, column=1, sticky='WE')
#Collect Data Button
self.Button2 = ttk.Button(self.frame_buttons, text="Collect Data" )
self.Button2.grid(row=1, column=2, sticky='WE')

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/323825.html
