Como mudar o tamanho de um JTextArea com o mouse?

Olá!

Eu estou precisando implementar uma interface na qual o usuário poderá alterar o tamanho de um JTextArea com o mouse, “puxando” pelas bordas, tal como se faz quando tu seleciona uma parte de uma imagem no Paint e dai tu aumenta o tamanho dela “puxando as bordas” com o mouse.

Eu até consegui aumentar o tamanho via código, mas eu precisava fazer pelo mouse e não tenho nem idéia de como fazer isso. Pensei em de repente utilizar alguma coisa por tras do JTextArea, mas não sei, vai que tenha uma maneira mais fácil.

Obrigado!

Essa implementação é bastante complexa.

Verifique se usar SplitPane já não resolve o seu problema.

Pois é, não é bem isso.

Na verdade eu quero permitir que o usuário coloque quantos “JtextArea” ele quiser no JPanel. Para isso ele clica num botao e clica na posicao do JPanel que ele quer que fique o JTextArea. Isso eu já consegui, e também mover o JTextArea, o problema é no resize com o mouse…

Eu pensei em repente desenhar um “retangulo” atras com uma altura e largura pouco maior que o textarea e que ele sirva para aumentar o tamanho, mas não sei se é o mais viável.

hummmm… então seu caso é realmente mais grave.

A solução do retângulo é boa. Eu realmente não consigo imaginar uma forma fácil de fazer o que você quer.
Mas provavelmente, envolverá estender o JTextArea e adicionar um mouseMotionListener sobre ele.

IDEs, como o netbeans, acharam a solução desse problema redesenhando tudo. Nada prático, mas não deixa de ser uma alternativa, pelo menos enquanto o usuário estiver movimentando/redimensionando objetos.

Pois é…

Eu adicionei já consigo mover os JTextAreas, o problema está no redimensionamento pelo mouse mesmo…

Se eu por exemplo, ao clicar no botao “Adicionar JTextArea”, desenhar um retangulo “atras” do JTextArea com, digamos, 5 pixeis a mais de largura e altura que o JTextArea, como eu adiciono um mousemotionlistener ao retangulo? Afinal, eu irei puxar o “retangulo”, e a medida que o tamanho dele muda, eu faço o jTextArea acompanhar.

Tem como adicionar MouseMotionListener a um “Rectangle” ?

Tive uma outra idéia que me parece ser mais viável…

Ao adicionar um JTextArea, adiciono 4 Rectangles nos cantos do JTextArea, dai ao mover um dos retangulos, mudo o tamanho do JTextArea de acordo com a disposição atual dos retangulos.

Mas, daí preciso saber quando o mouse vai estar por cima de certo retangulo, e volta a questao do mousemotionlistener no Rectangle…

No Rectangle não. Você precisa adicionar o mouseMotionListener no painel que contém o retângulo. E testar pelas coordenadas mesmo.

Entendi…

Existe algum metodo que teste se o mouse esta “dentro” do retangulo ou vou ter que fazer no braco isso?

Existe sim.

Desenhe retângulos usando a classe Rectangle2D:

Depois, para testar se o mouse está dentro de um retângulo basta usar o método contains. Ele aceita tanto as coordenadas x e y, quanto um Point (que o evento retorna).

Comecei a fazer aqui e já tive um problema que eu não estou entendendo.
Bom, criei uma classe que contem 1 JEditorPane (ao invés de textArea) e 2 Rectangles (1 para o canto superior esquerdo e outro para o inferior direito):

[code]public class CampoTexto implements MouseMotionListener, MouseListener {
private JEditorPane editor;
private Rectangle ds,di;
int baseX = -1;
int baseY = -1;
Container form;

public CampoTexto(Container f) {
    this.form = f;
    editor = new JEditorPane();
    editor.setBounds(0,0,60,60);
    editor.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
    editor.addMouseListener(this);
    editor.addMouseMotionListener(this);
    editor.setFocusable(true);
    ds = new Rectangle(0,0,8, 8);
    di = new Rectangle(60,60,8, 8);
}

public void monta(){
    desenhaQuadrados();
    form.add(editor);
}
public void desenhaQuadrados(){
    Graphics2D g2 = (Graphics2D) form.getGraphics();g2.fill(ds);
    g2.fill(ds);
    g2.fill(di);
}

public void redesenha(){
    form.repaint();
    desenhaQuadrados();
}

public void mouseDragged(MouseEvent e) {
    System.out.println("Dragged");
    if ((this.baseX != -1) && (this.baseY != -1)) {
        int x = editor.getX() + e.getX() - this.baseX;
        int y = editor.getY() + e.getY() - this.baseY;
        editor.setLocation(x, y);
        ds.setLocation(x-8, y-8);
        di.setLocation(x+editor.getWidth(), y+editor.getHeight());
        redesenha();
    }
}

public void mousePressed(MouseEvent e) {
    if(e.getButton()==e.BUTTON3){
        System.out.println("moved");
    this.baseX = e.getX();
    this.baseY = e.getY();
    }
}

public void mouseReleased(MouseEvent e) {
    if(e.getButton()==e.BUTTON3){
        System.out.println("released");
    this.baseX = -1;
    this.baseY = -1;
    }
    redesenha();
}

}[/code]

E instancio um objeto desta classe no onclick de um botao:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { CampoTexto t = new CampoTexto(jPanel2); t.monta(); }

O que está acontecendo é o seguinte: eu consigo MOVER o JEditorPane, só que os “retangulos” eles até se movem junto, mas “piscando” e quando eu paro de mover, os retangulos simplesmente desaparecem… Se eu volto a mover, eles aparecem piscando denovo, mas dai eu paro e eles desaparecem denovo.

Qual é o erro?

O java não mantém estado do que é desenhado no seu componente. O correto seria você fazer um filho do local onde você desenha, e sobrescrever o método paintComponent.

Além disso, você jamais deve alterar o estado do objeto graphics, recebido como parâmetro. O uso correto é assim:

public void paintComponent(Graphics g) {
   super.paintComponent(g);
   Graphics2D g2d = (Graphics2D) g.create(); //Faz uma cópia do Graphics
   //Faça a pintura aqui usando g2d
   g2d.dispose();  //Desfaz a cópia
}

Caso contrário, você pode ter efeitos estranhos.

O paintComponent é chamado sempre que a janela é redesenhada. Isso inclui, por exemplo, quando o usuário minimiza e maximiza a janela, quando algum outro aplicativo pula na frente da janela, etc.

Os eventos só alterarão os estados e chamarão o método repaint(). Mais ou menos como você já fez. O repaint se encarregada de chamar o paintComponent.