Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ошибка перерисовки JLabel со своим UI, Форма с JLabel не перерисовывается 
:(
    Опции темы
carper
  Дата 1.3.2005, 19:13 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Создаю свой UI для метки (в данном конкретном случае просто нужен объемный текст).

Проблема - форма (JFrame и т.п.), содержащая хотя бы одну такую самопальную метку, нормально перерисовывется ТОЛЬКО при изменении размера.

Если же, например, мы просто перекроем такое окошко окном другой программы, то, когда мы закроем эту др. программу, вновь появившееся окно будет содержать нормально отрисованную нашу самопальную метку!, а все остальные GUI компоненты "пропадут" (впредь до следующего изменения размера окна).

Т.е. такое впечатление, что эта моя самопальная метка должна как-то взаимодействовать с остальными компонентами, отслеживая invalidate и вызывая repaint для всех остальных компонентов - легко сказать, но непонятно почему это происходит и как сделать.


Ни в одном из примеров на SUN ничего подобного нет, точнее все примеры вроде бы говорят, что я все делаю правильно и заморачиваться с redraw "чужих" компонентов я не должен.



Ниже пример кода:

Код

public class Label3D extends JLabel {
public Label3D(String text){
   super(text);
    this.setUI(new 3DTransformUI());  //Назначим свой менеджер для рисования метки
}


public static void main(String[] args) {
   JFrame flt = new JFrame("Demo 3D Label");
   flt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   JFrame.setDefaultLookAndFeelDecorated(true);
   Container contentPane = flt.getContentPane();
   contentPane.setLayout(new FlowLayout());

   Label3D ml = new Label3D("Тень");
   ml.setToolTipText("Это тоже работает странно - попробуйте навести курсор ближе к краю");
   ml.setForeground(Color.BLUE);
   ml.setFont(new Font("Arial", Font.PLAIN, 72));
   ml.setIcon(new ImageIcon("prefs_24.gif"));

   contentPane.setBackground(Color.WHITE);
   contentPane.add(ml);

   flt.pack();
   flt.setVisible(true);
   }

}



private  class 3DTransformUI extends BasicLabelUI {
private static Rectangle paintIconR = new Rectangle();
 private static Rectangle paintTextR = new Rectangle();
 private static Rectangle paintViewR = new Rectangle();
 private static Insets paintViewInsets = new Insets(0, 0, 0, 0);
 private int ShadowWidth= 3;

 public int setShadowWidth(int newWidth){
   if (newWidth>3) {
     ShadowWidth = newWidth; return newWidth;
   } else return 3;
 }

  public int getShadowWidth(){
    return ShadowWidth;
  }

private void DrawTxt(String clippedText, Color newColor, JLabel label, Graphics g,
                      int textX, int textY, int dx, int dy, boolean islblenabled) {
   label.setForeground(newColor);
   if (islblenabled){
     paintEnabledText(label, g, clippedText, textX + dx, textY + dy);
   } else {
     paintDisabledText(label, g, clippedText, textX + dx, textY + dy);
   }
 }


public void paint(Graphics gr, JComponent c) {
   Graphics2D g= (Graphics2D)gr;        
   JLabel label = (JLabel) c;
   String text = label.getText();
   Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();

   if ((icon == null) && (text == null)) {
       return;
   }

   FontMetrics fm = g.getFontMetrics();
   paintViewInsets = c.getInsets(paintViewInsets);

    paintViewR.x = paintViewInsets.left;
   paintViewR.y = paintViewInsets.top;

   paintViewR.height = c.getHeight()- ShadowWidth;
   paintViewR.width = c.getWidth()  + ShadowWidth;

   paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
   paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;

   String clippedText =
         layoutCL(label, fm, text, icon, paintViewR, paintIconR, paintTextR);

   if (icon != null) {
      icon.paintIcon(c, g, paintIconR.x, paintIconR.y);
   }

   if (text != null) {
     int textX = paintTextR.x;
     int textY = paintTextR.y + fm.getAscent() - ShadowWidth;
     Color oldColor = label.getForeground();
     AffineTransform oldaft = g.getTransform();

       
      DrawTxt(clippedText, new Color(209,209,209), label, g, textX, textY, ShadowWidth, ShadowWidth, label.isEnabled());

     double dx= ShadowWidth*0.66;
     double dy= dx-0.1;

     AffineTransform aft = AffineTransform.getRotateInstance(-(0*3.14)/180);
     aft.concatenate(new AffineTransform(1.0,0,0,1.0,dx,dy));
     g.setTransform(aft);
     DrawTxt(clippedText, new Color(150,150,150), label, g, textX, textY, 0, 0,label.isEnabled());

     g.setTransform(oldaft);
      DrawTxt(clippedText, new Color(200,200,200), label, g, textX, textY, 1, 1,label.isEnabled());

     //А теперь рисуем сам текст
     label.setForeground(oldColor);
     DrawTxt(clippedText, oldColor, label, g, textX, textY, 0, 0, label.isEnabled());

   } //end if


 }

}


  Вверх
AntonSaburov
Дата 1.3.2005, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 10
Всего: 118



А как это можно собрать

Код

this.setUI(new 3DTransformUI());  //Назначим свой менеджер для рисования метки


3DTransform - такое имя разве возможно ?
Добавлено @ 19:21
Кроме того, надо посмотреть - отвечает ли у тебя твоя метка за прорисовку своего фона. Если отвечает, то вообщем-то она действительно сама должна просить прорисоваться всем компонентам. Может она у тебя занимает всю область ?

Текст проверить никак - ибо не мал (лениво немного smile ), а запустить не получается.
PM MAIL WWW ICQ   Вверх
LSD
Дата 1.3.2005, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 38
Всего: 538



Я не понял, пока в чем дело но этот код у меня дает 100% загрузку процессора.
Правда есть один момент, не знаю имеет ли он отношение к делу:
Код
AffineTransform aft = AffineTransform.getRotateInstance(-(0*3.14)/180);



--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
carper
Дата 2.3.2005, 09:22 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











AntonSaburov
Прошу прощения - не 3DTransformUI, было test3DTransformUI - при задании вопроса я попытался сократить имя до удобочитаемого и слегка промахнулся. smile


LSD
Нет 100% загрузки у меня нет, зато есть 50%, что тоже очень много!!!
Боюсь, что проблемы с перерисовкой остальных компонентов и подозрительная загрузка процессора одного поля ягоды, я заметил это только после Вашего сообщения. (JAVA 1.5)

AffineTransform aft = AffineTransform.getRotateInstance(-(0*3.14)/180); - Это пустышка, оставленная из-за того, что меня не удовлетворяет получаемая тень (слишком четкая) и я пытаюсь экспериментировать с кодом -отсюда и умножение на 0. (умножение на реальное число никакого улучшения ситуации не дает).



AntonSaburov
"Кроме того, надо посмотреть - отвечает ли у тебя твоя метка за прорисовку своего фона. "
Я привел полный код, того, что она делает.


"Если отвечает, то вообщем-то она действительно сама должна просить прорисоваться всем компонентам."
Каким образом она должна это сделать и почему?


"Может она у тебя занимает всю область ?"
Да вроде как нет. По крайней мере в своем коде я вроде как не могу найти места, где она бы пыталсь расползтись на всю область.
Я пробовал размещать другие компоненты на различных панелях и использовать различные Layout Managers - эффект абсолютно то же - наличие такой метки загадочно отдает команду всем остальным (СТАНДАРТНЫМ) компонентам отрисовываться только при ресайзе. А сама моя кривая метка радостно демонстрирует абсолютно правильную перерисовку во всех остальных случаях.

Попробуйте добавить в main такой код :
JLabel mll= new JLabel("ЧТОТОЕЩЕ");
mll.setForeground(Color.BLUE);
mll.setFont(new Font("Arial", Font.PLAIN, 72));
contentPane.add(mll);

И посмотрите как себя поведет эта вторая метка.



P.S. В общем-то очевидно, что проблема именно в моем коде, это никак на баг JAVA, но что-то я
запутался совсем. smile
  Вверх
carper
Дата 2.3.2005, 10:09 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Вроде бы проблема в строчке
DrawTxt(clippedText, new Color(209,209,209), label, g, textX, textY, ShadowWidth, ShadowWidth, label.isEnabled());

Точнее в последующем затем вызове
label.setForeground(newColor); - Именно здесь и возникают проблемы, если цвет отличается от первоначального.

Т.е. понятно, что назначив новый цвет я принимаю на себя какие-то доп. обязательства вот только не ясно какие.

Кажется именно про это говорил AntonSaburov, но что с этим деалать на практике я не понимаю. smile
  Вверх
LSD
Дата 3.3.2005, 00:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 38
Всего: 538



Я понял в чем причина 100% загрузки проца:
Код
private void DrawTxt(String clippedText, Color newColor, JLabel label, Graphics g, int textX, int textY, int dx, int dy, boolean islblenabled)
{
 label.setForeground(newColor);// проблема тут
 if(islblenabled)
 {
   paintEnabledText(label, g, clippedText, textX + dx, textY + dy);
 }
 else
 {
    paintDisabledText(label, g, clippedText, textX + dx, textY + dy);
  }
}

Вы меняете цвет компонента во время его перерисовки, что вызывает его перересовку, отсюда и бесконечный цикл.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
carper
Дата 3.3.2005, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 4
Всего: 8



LSD
Да, спасибо большое. Именно так все и происходило.

Теперь закономерно возникает вопрос (поскольку я все еще надеюсь, что мне удастся сделать трехмерной именно JLabel) как можно поменять цвет?
Ведь в случае метки я не могу работать напрямую с кистями?

PM MAIL   Вверх
carper
Дата 3.3.2005, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 4
Всего: 8



Что-то ступил, никто же мне не мешает использовать:
g.setColor(...);
BasicGraphicsUtils.drawString(g,clippedText,32, textX,textY);

Вопрос теперь в другом, что-то у меня теперь все хорошо с загрузкой процессора и цветами, да вот только теперь имею обратную картину smile - все отлично перерисовывается кроме самой моей многострадальной метки.
Непонятно - я же не перекрывал стандартный actionListener для BasicLabelUI, чего же это он не вызывает мой paint на invalidate?
PM MAIL   Вверх
LSD
Дата 3.3.2005, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 38
Всего: 538



Косяк здесь:
Код
AffineTransform aft = AffineTransform.getRotateInstance(-(0*3.14) / 180);
aft.concatenate(new AffineTransform(1.0,0,0,1.0,dx,dy));
g.setTransform(aft);
DrawTxt(clippedText, new Color(150,150,150), label, g, textX, textY, 0, 0,label.isEnabled());

Если DrawTxt закоментарить, то все будет нормально перерисовываться.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
carper
Дата 4.3.2005, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 4
Всего: 8



LSD
"Если DrawTxt закоментарить, то все будет нормально перерисовываться. "

Если его закомментировать, то нечему будет нормально перерисовываться. smile


Сейчас исправленный текст этой функции выглядит так:

Код

private void DrawTxt(String clippedText, Color newColor, JLabel label, Graphics g,
                      int textX, int textY, int dx, int dy, boolean islblenabled) {
    if (islblenabled){
     g.setColor(newColor);
     BasicGraphicsUtils.drawString(g,clippedText,label.getDisplayedMnemonic(), textX+dx,textY+dy);
     //paintEnabledText(label, g, clippedText, textX + dx, textY + dy); ////Рисуем цветом Foreground
   } else {
     g.setColor(label.getBackground());
     BasicGraphicsUtils.drawString(g,clippedText,label.getDisplayedMnemonic(), textX+dx,textY+dy);
     //paintDisabledText(label, g, clippedText, textX + dx, textY + dy); //Рисуем цветом Background
   }
 }



Все работает - процессор не грузит, при сворачивании-разворачивании, изменении размеров или при перекрытии другим окошком ВСЕ нормально работает.
Единственный косяк в ToolTips - после всплывающей подсказки на фоне моей метки прерисовка не происходит, точнее лезут артифакты.

На сайте SUN нашел маловразумительную подсказку, что если использовать AffineTransform и/или
opaque в paint(), то возможны артефакты, а вот как с этим бороться не понял.

PM MAIL   Вверх
AntonSaburov
Дата 4.3.2005, 10:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 10
Всего: 118



Цитата(carper @ 4.3.2005, 10:28)
На сайте SUN нашел маловразумительную подсказку, что если использовать AffineTransform и/или opaque в paint(), то возможны артефакты, а вот как с этим бороться не понял.

Сильно подозреваю, что в таком случае единого решения может и не найдется. Придется копаться и "бить в бубен". Если решение найдется - будем крайне признательны, если поделишься. Удачи.
PM MAIL WWW ICQ   Вверх
LSD
Дата 4.3.2005, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 38
Всего: 538



Цитата(carper @ 4.3.2005, 10:28)
Если его закомментировать, то нечему будет нормально перерисовываться.

Надо закоментарить только тот что я выделил, и тогда остальные 3 будут нормально перерисовываться.
Вот что у меня получилось, все нормально перерисовывается, включая ToolTips
Добавлено @ 21:17
Я думаю проблема в одном из AffineTransform.

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  Label3D.zip


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
carper
Дата 5.3.2005, 10:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 227
Регистрация: 2.3.2005

Репутация: 4
Всего: 8



LSD
Н-да, во-первых, если я правильно понял, в первом варианте перерисовка происходила не из-за setForegraundColor, а из-за affineTransform (ну, или из-за сочетания того и другого) ?

Мои дальнейшие эксперименты , см. мой пост выше, показали, что избежать зацикливания из-за
affineTransform все же можно, но тогда попадаем на проблему с ToolTips.

Или же можно избавиться вообще от affineTransform и использовать Ваш вариант, тогда получим тень, но кривоватую - собственно все мои affineTransform именно и возникли из-за желания нарисовать нечто хоть чуть более правдоподобное, чем просто серая буква смещенная на n пискселей.

С ToolTips я уперся в проблему того, что я просто не понимаю, из-за чего тут-то возникает проблема?
Ну, понятно, что для ускорения перерисовывается скорее всего область, перекрываемая ToolTips, таким образом, методу paint может быть дана команда на перисовку не всей обасти, а только части, что и приводит к косяку.
Остается найти в моем коде место, где учитывается динамически изменяемая область рисования.
Я пока найти так и не смог.

Код

package LSDlabels3D;

import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.plaf.basic.BasicGraphicsUtils;
import javax.swing.plaf.LabelUI;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;


/public class LSD3DTransformUI extends BasicLabelUI {
 private static Rectangle paintIconR = new Rectangle();
 private static Rectangle paintTextR = new Rectangle();
 private static Rectangle paintViewR = new Rectangle();
 private static Insets   paintViewInsets = new Insets(0, 0, 0, 0);
 private static Color SColor= new Color(209,209,209);
 private int ShadowWidth= 3;

 public int setShadowWidth(int newWidth){
   if (newWidth>3) {
     ShadowWidth = newWidth; return newWidth;
   } else return 3;
 }

 public int getShadowWidth(){
   return ShadowWidth;
 }

 //Пока переопределенный метод ничего не делает - оставлен, т.к. рисование объемного
 //текста может потребовать чуть больше пространства, чем плоский текст
  public Dimension getPreferredSize(JComponent c) {
    Dimension dim = super.getPreferredSize(c);
    return (dim);
 }

 private void DrawTxt(String clippedText, Color newColor, JLabel label, Graphics g,
                      int textX, int textY, int dx, int dy, boolean islblenabled) {
    if (islblenabled){
     g.setColor(newColor);
     BasicGraphicsUtils.drawString(g,clippedText,label.getDisplayedMnemonic(), textX+dx,textY+dy);
     
   } else {
     g.setColor(label.getBackground());
     BasicGraphicsUtils.drawString(g,clippedText,label.getDisplayedMnemonic(), textX+dx,textY+dy);
     
   }
 }

public void paint(Graphics gr, JComponent c) {
   Graphics2D g= (Graphics2D)gr;
   JLabel label = (JLabel) c;
   String text = label.getText();
   Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();

   if ((icon == null) && (text == null)) {
       return;
   }

   FontMetrics fm =    g.getFontMetrics(); //ОТ ОБЛАСТИ НЕ ЗВАИСИТ
   paintViewInsets = c.getInsets(paintViewInsets); //ОТ ОБЛАСТИ НЕ ЗАВИСИТ?

   //Учтем толщину бордюра (если он, конечно, есть у нашей метки)
   paintViewR.x = paintViewInsets.left;
   paintViewR.y = paintViewInsets.top;

   paintViewR.height = c.getHeight() - ShadowWidth; //ОТ ОБЛАСТИ НЕ ЗАВИСИТ
   paintViewR.width  = c.getWidth()  + ShadowWidth;

   paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
   paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;

   String clippedText =   layoutCL(label, fm, text, icon, paintViewR, paintIconR, paintTextR);

   if (icon != null) {
      icon.paintIcon(c, g, paintIconR.x, paintIconR.y);
   }

   if (text != null) {
     int textX = paintTextR.x + c.getX(); //А вот тут возможно что-то есть! Но не помогает. :(
  int textY = paintTextR.y + fm.getAscent() - ShadowWidth+c.getY();
     Color oldColor = label.getForeground();
     AffineTransform oldaft = g.getTransform();

     g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
     g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
     g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
      double dx= ShadowWidth*0.66;
     double dy= dx-0.1; //Сдвиг тени по оси Y всегда немного меньше, чем по оси X
 
      AffineTransform aft=  AffineTransform.getTranslateInstance(dx,dy);
     g.setTransform(aft);

     DrawTxt(clippedText, new Color(150,150,150), label, g, textX, textY, 0, 0, label.isEnabled());
     //DrawTxt(clippedText, Color.RED, label, g, textX, textY, 0, 0, label.isEnabled());

     // g.setTransform(oldaft); - Работает очень странно
     g.setTransform(AffineTransform.getTranslateInstance(-dx,-dy)); //А так хорошо.
     DrawTxt(clippedText, new Color(200,200,200), label, g, textX, textY, 1, 1,label.isEnabled());

     //А теперь рисуем сам текст
     DrawTxt(clippedText, oldColor, label, g, textX, textY, 0, 0, label.isEnabled());
     g.setTransform(oldaft); //Можно и отключить, все равно ничего не дает

   //  Подозреваю, что где-то я неверно трансформирую объект, точнее неправильно
  // возвращаю его к испходному состоянию
     
   } //end if


 }
}




PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   jk1
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема »


 




[ Время генерации скрипта: 0.0931 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.