问题描述
|
我组装Tk窗口的方式有问题(在Win XP下,使用R tcltk和tcltk2)
library(tcltk)
library(tcltk2)
expandTk <- function() {
root <- tktoplevel()
# textBox with scroll bars
textBox <- tk2frame(root)
scr <- tkscrollbar(textBox,repeatinterval=5,command=function(...) tkyview(txt,...))
txt <- tktext(textBox,bg=\"white\",font=\"courier\",wrap=\"word\",yscrollcommand=function(...)tkset(scr,...))
tkpack(txt,side=\"left\",fill=\"both\",expand=TRUE)
tkpack(scr,side=\"right\",fill=\"y\")
tkmark.set(txt,\"insert\",\"0.0\")
tkpack(textBox,expand=TRUE)
# status bar and size grip
statusText <- tclVar(\"\")
f <- tk2frame(root,relief=\"sunken\")
l <- tk2label(f,textvariable=statusText)
tkpack(l,pady=2,padx=5,expand=0,fill=\"x\")
tkpack(f,expand=1,fill=\"x\",anchor=\"s\")
sg <- ttksizegrip(root)
tkpack(sg,anchor=\"se\")
}
窗口看起来不错,但是一旦我调整它的大小(即减小它的大小),滚动条和状态栏就会消失。我很确定这是一个用户错误,我已经看到其他Tk应用程序可以正确调整大小,但是我不知道应该使用哪个选项...
任何提示表示赞赏,
卡斯滕
解决方法
这是Tk
pack
几何管理器的标准行为。这是pack
手册页的相关部分:
如果腔体变得太小而无法满足奴隶的需求,那么
将给奴隶任何剩余的空间。如果腔缩小
到零大小,那么装箱单上所有剩余的奴隶将不被映射
屏幕,直到主窗口变得足够大以再次容纳它们。
因此,如果将整个窗口缩小到小于文本小部件请求的空间,则其他小部件将不留空间,并且它们将被映射。
最好的解决方案是使用grid
几何管理器,而不是pack
。一般来说,我发现mileage3ѭ比pack
更容易使用和强大,尽管里程可能会有所不同。特别是,它消除了对许多多余框架小部件的需求,从而可以大大简化您的代码。
我认为您可以使用以下方式:
expandTk <- function() {
root <- tktoplevel()
# textbox with scroll bars
textbox <- tk2frame(root)
txt <- tktext(textbox,bg=\"white\",font=\"courier\",wrap=\"word\",yscrollcommand=function(...)tkset(scr,...))
scr <- tkscrollbar(textbox,repeatinterval=5,command=function(...) tkyview(txt,...))
tkmark.set(txt,\"insert\",\"0.0\")
# Set up the geometry for the stuff inside the \"textbox\" frame.
# The text and scrollbar widgets live on the same row.
tkgrid(txt,scr)
# The text widget should stick to all four sides of its parcel.
tkgrid.configure(txt,sticky=\"nsew\")
# The scrollbar should stick to the top and bottom of its parcel,it need not stick to the
# left and right.
tkgrid.configure(scr,sticky=\"ns\")
# When the window is resized,we want surplus space to be allocated to the text widget,# which is in the top left corner of this frame.
tkgrid.columnconfigure(textbox,weight=1)
tkgrid.rowconfigure(textbox,weight=1)
# status bar and size grip
statusText <- tclVar(\"\")
l <- tk2label(root,textvariable=statusText,relief=\"sunken\")
sg <- ttksizegrip(root)
# Set up the geometry for the stuff inside the \"root\" window.
# First row is just the textbox frame...
tkgrid(textbox)
# Second row is the status label and the resize gadget
tkgrid(l,sg)
# The textbox widget should span 2 colums,and stick to all four sides of its parcel.
tkgrid.configure(textbox,columnspan=2,sticky=\"nsew\")
# The status label should stick to all four sides of its parcel too
tkgrid.configure(l,sticky=\"nsew\")
# The resize gadget should only stick to the bottom right of its parcel
tkgrid.configure(sg,sticky=\"se\")
# When the window is resized,we want surplus space to go to the textbox frame (and from there
# to the text widget itself,which it will do thanks to the grid weights we set up above). The
# textbox frame is in the top left corner of its parent window.
tkgrid.columnconfigure(root,weight=1)
tkgrid.rowconfigure(root,weight=1)
}
这里有一些有关使用R中的grid
几何管理器的更多信息。
, 如果您坚持包装小部件,则应注意,如果没有足够的空间来为所有小部件提供他们所要求的空间,则空间优先于打包的第一个小部件(在特定容器中)。首先将状态栏放入,然后将滚动条放入,然后仅将主小部件放入。 (您可能需要在包装特定小部件的一侧进行更改,以使其正常工作。)此外,如果它变得太复杂,请记住可以将内部框架包装在内部;给您很大的灵活性。
但这就是使用网格几何管理器的意义所在。当您使用应用的最后10%外观时,它可以为您提供更好的控制,并且不需要太多的窗口小部件嵌套即可实现。
, 正如Eric指出的那样,绝对网格是最好的,但是如果您真的想使用pack,那么调整扩展txt小部件的大小(如下所示)将为您提供所需的东西。有一些可以改进的启发式算法。
将此添加到代码末尾:
widthOfChar <- ceiling(as.numeric(tclvalue(tcl(\"font\",\"measure\",\"TkTextFont\",\"0123456789\")))/10) + 2
tkbind(root,\"<Configure>\",function(W) {
w.width <- as.integer(tkwinfo(\"width\",W))
txt.width <- w.width - 15L
tkconfigure(txt,width=floor(txt.width/widthOfChar))
})