我觉得这个可能是JScrollPane的一个bug,不过影响也不是很大呀,不就是要人手工拉一下吗,这样把,你就人工改成可以显示到你需要文本的最后一行呀,比如加个空行:sp4 = new JScrollPane(t4,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),t4.append("appned 33 \n");
这样它就可以显示你所要加的全部文本了呀,因为最后一行已经变成空行\n了
不好意思,我只能想出这个治标不治本的方法了。
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER),t4.append("appned 33 \n");
这样它就可以显示你所要加的全部文本了呀,因为最后一行已经变成空行\n了
不好意思,我只能想出这个治标不治本的方法了。
scrollRectToVisible(modelToView(m_doc.getLength()));
to overcome.
下面的代码中,表格中有新行插入后,还是强行滚动到第一行,供你参考
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import java.util.*;public class SplitTest extends JFrame {
JScrollPane sp1 = new JScrollPane();
JTable table = new JTable();
DefaultTableModel tm = new DefaultTableModel();
public SplitTest() {
this.setSize(400, 300);
this.getContentPane().add(sp1, BorderLayout.CENTER);
sp1.getViewport().add(table);
tm.addColumn("c1");
tm.addColumn("c2");
tm.addColumn("c3");
table.setModel(tm);
java.util.Timer timer = new java.util.Timer();
timer.schedule(new TimerTask() {
public void run() {
refreshTable();
}
}, 0, 2000);
}
void refreshTable() {
Vector row = new Vector();
for (int i = 0; i < 3; i++) {
row.add("value " + Integer.toString(i));
}
tm.addRow(row);
table.scrollRectToVisible(new Rectangle(0, 0, table.getSize().width, table.getSize().height)); //强行把显示滚动到第一行(其实是顶端)
System.out.println("add new row into tablemodel.");
}
public static void main(String[] args) {
SplitTest frame = new SplitTest();
frame.setVisible(true);
}
}
我把这个类的相关code贴出来,有兴趣地看一下吧。
package ClientMessage;/**
* <p>Title: JavaMe</p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: ISMT, HKUST</p>
* @author group4
* @version 1.0
*/import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import com.borland.jbcl.layout.*;
import javax.swing.border.*;import PropertyManager.*;
import MainApplication.*;
import ClientMessage.*;
public class MessageBox extends JSplitPane implements ActionListener
{
protected JPanel lowerPanel = new JPanel();
protected BorderLayout borderLayout1 = new BorderLayout();
protected JButton sendButton = new JButton();
protected JPanel upperPanel = new JPanel();
protected JPanel controlPanel = new JPanel();
protected MyTextArea displayArea = new MyTextArea();
protected JScrollPane upperScrollPane = new JScrollPane();
protected BorderLayout borderLayout2 = new BorderLayout();
protected JScrollPane lowerScrollPane = new JScrollPane();
protected JTextArea sendArea = new JTextArea();
protected Border border1;
protected PlainButton blockButton = new PlainButton();
protected PlainButton fontButton = new PlainButton();
protected PlainButton colorButton = new PlainButton();
protected FlowLayout flowLayout1 = new FlowLayout();
protected Border border2, border3; protected JTextField wordCountField = new JTextField(3); protected int type = 1; public MessageBox(int type)
{
jbInit();
this.type = type;
}
//this method is declared as protected to make it able to be inherited
protected void jbInit()
{
wordCountField.setEditable(false);
//create the border
border1 = BorderFactory.createCompoundBorder(new EtchedBorder(EtchedBorder.RAISED,
Color.blue,new Color(178, 178, 178)),BorderFactory.createEmptyBorder(5,5,1,4)); border2 = BorderFactory.createCompoundBorder(new TitledBorder(BorderFactory.createEtchedBorder(Color.white,Color.blue),""),BorderFactory.createEmptyBorder(2,2,2,2));
border3 = BorderFactory.createCompoundBorder(new TitledBorder(BorderFactory.createEtchedBorder(Color.white,Color.red),""),BorderFactory.createEmptyBorder(2,2,2,2));
this.setDividerLocation(360);
this.setOrientation(JSplitPane.VERTICAL_SPLIT);
this.setDividerSize(2);
this.setResizeWeight(1.0);
lowerPanel.setLayout(borderLayout1);
sendButton.setBorder(border2);
sendButton.setText("Send");
sendButton.addMouseListener(new MouseAdapter() // set the effect for the send button
{
public void mouseEntered(MouseEvent e)
{
sendButton.setBorder(border3);
}
public void mouseExited(MouseEvent e)
{
sendButton.setBorder(border2);
}
});
//set the starting value of the word count field
wordCountField.setText(String.valueOf(0)); upperPanel.setLayout(borderLayout2);
displayArea.setBorder(border1);
/*displayArea.setText("Venus0608 wrote:\nHello World\nHello World\nthis is my first game\n"
+"who are you after all?\nI am from china, what about you?"
+"Thanks a lot. this is from Cananda\n.. goood, thank you for you kindness\n");*/
//displayArea.setLineWrap(true);
//displayArea.setWrapStyleWord(true);
displayArea.setBackground(PropertyManager.Parameters.currentBackgroundColor);
displayArea.setFont(PropertyManager.Parameters.currentDefaultFont);
displayArea.setDocument(new DefaultStyledDocument()); controlPanel.setMinimumSize(new Dimension(9, 20));
controlPanel.setLayout(flowLayout1);
sendArea.setBorder(border1);
sendArea.setDocument(new MyDocument()); //set the default document to be MyDocument
sendArea.setText("Send message here");
sendArea.setLineWrap(true);
sendArea.setWrapStyleWord(true);
sendArea.setBackground(Parameters.currentBackgroundColor);
sendArea.setFont(Parameters.currentDefaultFont); //register key listeners to the sendArea
sendArea.registerKeyboardAction(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
sendButton.doClick();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,KeyEvent.CTRL_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW);
//buttons
blockButton.setText("Block");
blockButton.setIcon(new ImageIcon("images\\stop.gif"));
fontButton.setText("Font");
fontButton.setIcon(new ImageIcon("images\\font.gif"));
fontButton.addActionListener(this);
colorButton.setText("Color");
colorButton.setIcon(new ImageIcon("images\\color.gif"));
colorButton.addActionListener(this); this.add(lowerPanel, JSplitPane.BOTTOM);
lowerPanel.add(sendButton, BorderLayout.EAST);
lowerPanel.add(lowerScrollPane, BorderLayout.CENTER); lowerScrollPane.getViewport().add(sendArea, null);
this.add(upperPanel, JSplitPane.TOP);
upperPanel.add(upperScrollPane, BorderLayout.CENTER);
upperPanel.add(controlPanel, BorderLayout.SOUTH); controlPanel.add(blockButton, null);
controlPanel.add(fontButton, null);
controlPanel.add(colorButton, null);
controlPanel.add(Box.createHorizontalStrut(2));
controlPanel.add(wordCountField, null); displayArea.setEditable(false);
upperScrollPane.getViewport().add(displayArea, null);
}
//get the sended message
public String getOutMessage()
{
try{
return sendArea.getText();
}
catch(NullPointerException npe)
{
return null;
}
}
public void clearDisplayArea()
{
displayArea.setText("");
}
//clear the sendArea
public void clearSendArea()
{
sendArea.setText("");
sendArea.requestFocus();
} //set client message header
public synchronized void setInMessage(String from,
String to, boolean ownMessage, String message)
{
displayArea.appendInMessage(from, to, ownMessage, message);
//upperScrollPane.getVerticalScrollBar()
// .setValue(upperScrollPane.getVerticalScrollBar().getMaximum());
upperScrollPane.getViewport().scrollRectToVisible(new Rectangle(0,
displayArea.getHeight()-upperScrollPane.getHeight()+25,
displayArea.getWidth(), upperScrollPane.getHeight()-25));
}
public synchronized void setAlertMessage(String message)
{
SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setForeground(attr, Color.GREEN);
displayArea.append(message+"\n", attr);
//lowerScrollPane.getVerticalScrollBar()
// .setValue(upperScrollPane.getVerticalScrollBar().getMaximum());
upperScrollPane.getViewport().scrollRectToVisible(new Rectangle(0,
displayArea.getHeight()-upperScrollPane.getHeight()+25,
displayArea.getWidth(), upperScrollPane.getHeight()-25));
}
//get the send button
public JButton getSendButton() { return sendButton; }
//get the block button
public PlainButton getBlockButton() { return blockButton; }
//get the font button
public PlainButton getFontButton() { return fontButton; }
//get the colorbutton
public PlainButton getColorButton() { return colorButton; }
//get the display area
public MyTextArea getDisplayArea() { return displayArea; }
//get send area
public JTextArea getSendArea() { return sendArea; }
//remove block button
public void removeBlockButton() { controlPanel.remove(blockButton); } //set the color of control panel
public void setControlPanelColor(Color color)
{ controlPanel.setBackground(color); }
//add buttons to the control panel for customization
public void addJButtonToControlPanel(JButton button)
{
controlPanel.add(button);
}
//set the divider location
public void setMessageBoxDividerLocation(int location)
{
this.setDividerLocation(location);
}
//set the font of the display area and send area
public void setFont(java.awt.Font font, boolean applyToDisplayArea, boolean applyToSendArea)
{
if(applyToDisplayArea == true)
{
displayArea.setFont(font);
}
if(applyToSendArea == true)
{
sendArea.setFont(font);
}
} //set the background color of the display area and send area
public void setBackgroundColor(Color color, boolean applyToDisplayArea, boolean applyToSendArea)
{
if(applyToDisplayArea == true)
{
displayArea.setBackground(color);
}
if(applyToSendArea == true)
{
sendArea.setBackground(color);
}
} //action listener method
public void actionPerformed(ActionEvent event)
{
//font button
if(event.getSource() == fontButton)
{
FontChooser fontChooser = new FontChooser(null, "Font Chooser", true, displayArea.getFont());
int option = fontChooser.showFontChooser();
if(option == FontChooser.OK_OPTION)
{
Font font = fontChooser.getSelectedFont();
setFont(font, true, true);
//set the default value for new instances of this messagebox
Parameters.currentDefaultFont = font;
}
else
{
return;
}
} //color button
if(event.getSource() == colorButton)
{
Color color = JColorChooser.showDialog(this, "Chooser background color", displayArea.getBackground());
setBackgroundColor(color, true, true);
//set the default value
Parameters.currentBackgroundColor = color;
}
}
//my modified document
class MyDocument extends DefaultStyledDocument implements DocumentListener
{
int maxLength = Parameters.MAX_MESSAGE_LENGTH; public MyDocument()
{
super();
this.addDocumentListener(this);
if(type == 1)
{
maxLength = Parameters.MAX_MESSAGE_LENGTH;
}
else if(type == 2)
{
maxLength = Parameters.MAX_MULTICAST_MESSAGE_LENGTH;
}
} public void insertString(int offset, String str, AttributeSet a) throws BadLocationException
{
int lastPosition = this.getLength();
if( (lastPosition+str.length()) <= maxLength)
{
super.insertString(lastPosition, str, a);
}
else if(lastPosition <= maxLength && (lastPosition+str.length()) >= maxLength)
{
super.insertString(lastPosition, str.substring(0, maxLength-lastPosition), a);
}
} public void changedUpdate(DocumentEvent e) { }
//overried insertUpdate() method
public void insertUpdate(DocumentEvent e)
{
sendButton.setEnabled(true);
int oldCount = Integer.parseInt(wordCountField.getText());
wordCountField.setText(String.valueOf(oldCount+e.getLength()));
}
//override removeUpdate() method
public void removeUpdate(DocumentEvent e)
{
if(this.getLength() == 0)
{
sendButton.setEnabled(false);
}
int oldCount = Integer.parseInt(wordCountField.getText());
wordCountField.setText(String.valueOf(oldCount-e.getLength()));
}
}
}
我觉得主要问题可能是这下边的么?//set client message header
public synchronized void setInMessage(String from,
String to, boolean ownMessage, String message)
{
displayArea.appendInMessage(from, to, ownMessage, message);
//upperScrollPane.getVerticalScrollBar()
// .setValue(upperScrollPane.getVerticalScrollBar().getMaximum());
upperScrollPane.getViewport().scrollRectToVisible(new Rectangle(0,
displayArea.getHeight()-upperScrollPane.getHeight()+25,
displayArea.getWidth(), upperScrollPane.getHeight()-25));
}
public synchronized void setAlertMessage(String message)
{
SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setForeground(attr, Color.GREEN);
displayArea.append(message+"\n", attr);
//lowerScrollPane.getVerticalScrollBar()
// .setValue(upperScrollPane.getVerticalScrollBar().getMaximum());
upperScrollPane.getViewport().scrollRectToVisible(new Rectangle(0,
displayArea.getHeight()-upperScrollPane.getHeight()+25,
displayArea.getWidth(), upperScrollPane.getHeight()-25));
}
另外我还重载了DefaultStyledDocument的insertString方法,大家觉得这个有问题么?
public void insertString(int offset, String str, AttributeSet a) throws BadLocationException
{
int lastPosition = this.getLength();
if( (lastPosition+str.length()) <= maxLength)
{
super.insertString(lastPosition, str, a);
}
else if(lastPosition <= maxLength && (lastPosition+str.length()) >= maxLength)
{
super.insertString(lastPosition, str.substring(0, maxLength-lastPosition), a);
}
}
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import java.util.*;
import java.awt.event.*;
public class ScrollText extends JFrame {
private XYLayout xYLayout1 = new XYLayout();
private JScrollPane jScrollPane1 = new JScrollPane();
private JTextArea txt = new JTextArea();
Document m_doc = new DefaultStyledDocument();
boolean isContinue = true;
private JButton btnStop = new JButton();
public static void main(String[] args) {
ScrollText t = new ScrollText();
t.setSize(300,200);
t.show();
} public ScrollText() {
try {
jbInit();
txt.setDocument(m_doc);
}
catch(Exception e) {
e.printStackTrace();
}
new Thread(new Runnable() {
public void run() {
while(true) {
try{
Thread.sleep(1000);
if(isContinue)
m_doc.insertString(m_doc.getLength(),new Date()+"\nlast line\n",null);
txt.scrollRectToVisible(txt.modelToView(m_doc.getLength()));
}catch(Exception e){}
}
}
}).start();
}
private void jbInit() throws Exception {
this.getContentPane().setLayout(xYLayout1);
xYLayout1.setWidth(425);
xYLayout1.setHeight(289);
btnStop.setText("Stop");
btnStop.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
btnStop_actionPerformed(e);
}
});
this.getContentPane().add(jScrollPane1, new XYConstraints(58, 25, 291, 182));
this.getContentPane().add(btnStop, new XYConstraints(122, 236, 97, 24));
jScrollPane1.getViewport().add(txt, null);
} void btnStop_actionPerformed(ActionEvent e) {
isContinue = !isContinue;
btnStop.setText(isContinue?"Stop":"Resume");
}
}
displayArea.getHeight()-upperScrollPane.getHeight()+25,
displayArea.getWidth(), upperScrollPane.getHeight()-25));
你现在用的还是jviewport的scrollrecttovisible方法,改成
displayArea.getViewport().scrollRectToVisible(new Rectangle(0,
displayArea.getHeight()-upperScrollPane.getHeight()+25,
displayArea.getWidth(), upperScrollPane.getHeight()-25));
看看。《Java2图形设计V2 Swing》里说法是:一般很少直接调用JViewport.scrollRectToVisible方法,而是为视口的视图调用scrollRectToVisible方法。(你这个例子中upperScrollPane的视图就是displayArea)
你是试了我的方法还是最后一段代码(打印new Date()+"\nlast line\n"的)? 如果是最后一段代码,这就奇怪了,因为在我这里(JB7中),是跳到最后啊. 我是用JDK1.3.
displayArea.scrollRectToVisible(new Rectangle(0,
displayArea.getHeight()-upperScrollPane.getHeight()+25,
displayArea.getWidth(), upperScrollPane.getHeight()-25));