在Tkinter应用程序中自动向下滚动列表框

时间:2018-02-19 15:18:14

标签: python-3.x tkinter

大家好我正在使用tkinter创建这个聊天应用程序,除了我在我的列表框中发布的文本没有按照我想要的方式显示之外,它的工作方式非常完美。一旦列表框中的空间完成,我必须手动向下滚动才能看到最近的消息。我的问题是,我该怎么做才能使Listbox在填充时自动向下滚动。这是Listbox代码的一部分    lista=Listbox(raiz,font=('Arial')) lista.pack(side=LEFT,padx=10,pady=10,ipadx=200,fill=X,expand=True )

这就是我发布的地方:

def post(text,n=0):
   winsound.Beep(400,150)
   if n==0:
      lista.insert(END,text)
      campo.delete(0,1000)  
   else:
      for i in text:
          lista.insert(END,i)

如果你能帮助我,那就太好了。感谢!!!

2 个答案:

答案 0 :(得分:0)

在显示当前或插入

之前,您应该清除public class TreeView extends JPanel { //Class for drawing the Tree onto a panel private int radius = 20; private int levelGap = 50; ExpTree t; public TreeView(ExpTree t) { this.t = t; } protected void paintComponent(Graphics g) { super.paintComponents(g); if (t.getRoot() != null) { displayTree(g, t.getRoot(), getWidth() / 2, 30, getWidth() / 4); } } private void displayTree(Graphics g, ExpTree t, int x, int y, int gap) { g.drawOval(x - radius, y - radius, 2 * radius, 2 * radius); g.drawString(t.getLeafVal() + "", x - 6, y + 4); if (t.getlChild() != null) { connectCircles(g, x - gap, y + levelGap, x, y); displayTree(g, t.lChild, x - gap, y + levelGap, gap /2); } if (t.getrChild() != null) { connectCircles(g, x + gap, y + levelGap, x, y); displayTree(g, t.rChild, x + gap, y + levelGap, gap /2); } } private void connectCircles(Graphics g, int x1, int y1, int x2, int y2) { double d = Math.sqrt(levelGap * levelGap + (x2 - x1) * (y2 - y1)); int x11 = (int)(x1 - radius * (x1 - x2) / d); int y11 = (int)(y1 - radius * (y1 - y2) / d); int x21 = (int)(x2 + radius * (x1 - x2) / d); int y21 = (int)(y2 + radius * (y1 - y2) / d); g.drawLine(x11, y11, x21, y21); } } public class Test extends JFrame { public Test() { setSize(400, 400); setLayout(new BorderLayout()); JPanel jp = new JPanel(); add(jp); setVisible(true); } public static void main(String[] args) { Test test = new Test(); //create parse trees from input in console boolean done = false; boolean valid = false; Parser p = new Parser(); ExpTree myTree; System.out.println("Enter an expression to convert into postfix notation"); do { System.out.println("Enter an expression: "); try { myTree = p.parseLine(); } catch (ParseException e) { System.out.println("Invalid Expression: Ensure it ends with a semicolon"); continue; } System.out.println(myTree.toPostfix(myTree)); TreeView view = new TreeView(myTree); test.add(view); view.repaint(); System.out.println("Do you want to enter another expression? (y/n)"); do { String s = p.getLine(); switch (s) { case "y" : valid = true; done = false; continue; case "n" : valid = true; done = true; continue; default: valid = false; done = false; System.out.println("Invalid input: Must be y or n"); } } while (!valid); } while (!done); } } //Setup of the tree incase it's useful public class ExpTree { //Tree object that is created when an expression is parsed private int type; private Object leafVal; public ExpTree lChild, rChild; public static final int NUM = 0, VAL = 1, OP = 2; private StringBuffer sb = new StringBuffer(); public ExpTree(int type, Object leafVal, ExpTree l, ExpTree r) { this.type = type; this.leafVal = leafVal; this.lChild = l; this.rChild = r; } //return the forth expression, a postfix expression public String toPostfix(ExpTree t) { if (t != null) { toPostfix(t.lChild); toPostfix(t.rChild); sb.append(t.leafVal); sb.append(" "); } return sb.toString(); } public ExpTree getRoot() { return this; } public Object getLeafVal() { return leafVal; } public ExpTree getlChild() { return lChild; } public ExpTree getrChild() { return rChild; } } class ParseException extends RuntimeException { public ParseException(String s) { super("Invalid expression: "+s); } } public class Parser { private Lexer lex; public Parser() { lex = new Lexer(); } public ExpTree parseLine() { lex.init(); lex.getToken(); ExpTree result = parseExp(true); if (lex.token==Lexer.where) { lex.getToken(); ExpTree defs = parseDefList(); result = makeWhereTree(result, defs); } if (lex.token!=Lexer.semico) { throw new ParseException("semicolon expected"); } return result; } public String getLine() { return lex.getLine(); } private ExpTree parseExp(boolean idsAllowed) { ExpTree result = parseTerm(idsAllowed); { while (lex.token==Lexer.plus || lex.token==Lexer.minus) { int op = lex.token; lex.getToken(); if (op==Lexer.plus) result = makePlusTree(result, parseTerm(idsAllowed)); else result = makeMinusTree(result, parseTerm(idsAllowed)); } } return result; } private ExpTree parseTerm(boolean idsAllowed) { ExpTree result = parseOpd(idsAllowed); { while (lex.token==Lexer.times || lex.token==Lexer.div || lex.token==Lexer.mod) { int op = lex.token; lex.getToken(); if (op==Lexer.times) result = makeTimesTree(result, parseOpd(idsAllowed)); else if (op==Lexer.mod) result = makeModTree(result, parseOpd(idsAllowed)); else result = makeDivideTree(result, parseOpd(idsAllowed)); } } return result; } private ExpTree parseOpd(boolean idsAllowed) { ExpTree result; switch(lex.token) { case Lexer.num: result = makeNumberLeaf(lex.numval); lex.getToken(); return result; case Lexer.id: if (!idsAllowed) throw new ParseException("identifier not allowed in identifier defintion"); result = makeIdLeaf(lex.idval); lex.getToken(); return result; case Lexer.lp: lex.getToken(); result = parseExp(idsAllowed); if (lex.token!=Lexer.rp) throw new ParseException("right parenthesis expected"); lex.getToken(); return result; default: throw new ParseException("invalid operand"); } } private ExpTree parseDefList() { ExpTree result = parseDef(); while (lex.token==Lexer.and) { lex.getToken(); result = makeAndTree(result, parseDef()); } return result; } private ExpTree parseDef() { if (lex.token!=Lexer.id) throw new ParseException("definition must start with identifier"); char id = lex.idval; if (Character.isUpperCase(id)) throw new ParseException("upper-case identifiers cannot be used in defintion list"); lex.getToken(); if (lex.token!=Lexer.eq) throw new ParseException("'=' expected"); lex.getToken(); return makeDefTree(id, parseExp(false)); } // the next seven methods need to be modified for part 3 of the assignment static ExpTree makeNumberLeaf(int n) { return new ExpTree(ExpTree.NUM, n, null, null); // this method should return a new number leaf with value n created using your constructor // if you've used the abstract class approach you will probably need something like // return new NumLeaf(n); // if you've used an ExpTree class that stores the node kind you will probably need something like // return new ExpTree(ExpTree.numNode, n , null, null); } static ExpTree makeIdLeaf(char c) { return new ExpTree(ExpTree.VAL, c, null, null); // this method should return a new id leaf with value c } static ExpTree makePlusTree(ExpTree l, ExpTree r) { return new ExpTree(ExpTree.OP, '+', l, r); // this method should return a new plus node with children l and r created using your constructor // if you've used the abstract class approach you will probably need something like // return new OpNode('+', l, r); // or // return new PlusNode(l, r); // if you've used an ExpTree class that stores the node kind you will probably need something like // return new ExpTree(ExpTree.opMode, '+', l, r); } static ExpTree makeMinusTree(ExpTree l, ExpTree r) { return new ExpTree(ExpTree.OP, '-', l, r); // this method should return a new minus node with children l and r } static ExpTree makeTimesTree(ExpTree l, ExpTree r) { return new ExpTree(ExpTree.OP, '*', l, r); // this method should return a new times node with children l and r } static ExpTree makeDivideTree(ExpTree l, ExpTree r) { return new ExpTree(ExpTree.OP, '/', l, r); // this method should return a new divide node with children l and r } static ExpTree makeModTree(ExpTree l, ExpTree r) { return new ExpTree(ExpTree.OP, '%', l, r); // this method should return a new mod (%) node with children l and r } // the next three methods need to be modified for part 6 of the assignment - do not modify them if you have not attempted part 6 static ExpTree makeWhereTree(ExpTree l, ExpTree r) { // remove the following line if you modify this method; leave it here if you do not attempt part 6 System.out.println("Part 6 not attempted"); return null; // this method should return a new 'where' node with children l and r } static ExpTree makeAndTree(ExpTree l, ExpTree r) { return null; // this method should return a new 'and' node with children l and r } static ExpTree makeDefTree(char c, ExpTree t) { return null; // this method should return a new definition node with identifier c and child t // if your definition nodes have 2 children you should put a new id leaf in the left child and use t as the right child } } class Lexer { static final int err = 0, num = 1, id = 2, plus = 3, minus = 4, times = 5, div = 6, mod = 7, lp = 8, rp = 9, semico = 10, where = 11, and = 12, eq = 13; int token; char idval; int numval; private String line = ""; private BufferedReader buf; Lexer() { buf = new BufferedReader(new InputStreamReader(System.in)); } void init() { do try { line = buf.readLine().trim(); } catch(Exception e) { System.out.println("Error in input"); System.exit(1); } while (line.length()==0); } String getLine() { init(); return(line); } void getToken() { if (line.length()==0) token = err; else switch (line.charAt(0)) { case '+': token = plus; line = line.substring(1).trim(); break; case '-': token = minus; line = line.substring(1).trim(); break; case '*': token = times; line = line.substring(1).trim(); break; case '/': token = div; line = line.substring(1).trim(); break; case '%': token = mod; line = line.substring(1).trim(); break; case '(': token = lp; line = line.substring(1).trim(); break; case ')': token = rp; line = line.substring(1).trim(); break; case ';': token = semico; line = line.substring(1).trim(); break; case '=': token = eq; line = line.substring(1).trim(); break; default: if (Character.isDigit(line.charAt(0))) { token = num; numval = line.charAt(0) - '0'; int i = 1; while (i<line.length()&&Character.isDigit(line.charAt(i))) { numval = numval*10+line.charAt(i)-'0'; i++; } line = line.substring(i).trim(); } else if (Character.isLowerCase(line.charAt(0))) { char c = line.charAt(0); if (c=='w' && line.length()>=5 && line.charAt(1)=='h' && line.charAt(2)=='e' && line.charAt(3)=='r' && line.charAt(4)=='e') { token = where; line = line.substring(5).trim(); } else if (c=='a' && line.length()>=3 && line.charAt(1)=='n' && line.charAt(2)=='d') { token = and; line = line.substring(3).trim(); } else if (line.length()>1 && Character.isLetter(line.charAt(1))) { token = err; } else { token = id; idval = c; line = line.substring(1).trim(); } } else token = err; } } } 小部件
Listbox

或者您可以将新内容置于此def post(text,n=0): winsound.Beep(400,150) if n==0: lista.delete(0, END) # this to clear the listbox and display the current content in the listbox lista.insert(END,text) campo.delete(0,1000) else: for i in text: lista.insert(END,i) 之上,

Listbox

因为你没有发布你的完整代码或者假设这是怎么回事。

答案 1 :(得分:0)

您需要在lista.see(tkinter.END)之前的lista.insert(END,text)行中添加