大家好我正在使用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)
如果你能帮助我,那就太好了。感谢!!!
答案 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)
行中添加