I'm trying to write a kanban board. But if there are two and more stickers in one column, often the JToolBar with buttons will be shown only if you click on a sticker in this column for the firs time. I thought that there were some problems with coordinates, but I didn't found it. The StickerListener responds th event, even prints "условие работает" if coordinates are correct, but the JToolBar remainds invisible.
import java.awt.*;
import javax.swing.*;
public class Main {
public static void main(String[] args)
{
Window window = new Window();
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Window extends JFrame {
public JButton Edit;
public JButton Read;
public JButton Delete;
private Window window;
private JToolBar jtb;
public boolean stickerToolBarActivated;
public Window() {
window= this;
setSize(500, 500);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
Desk d = new Desk();
createMenu(d);
add(d);
setDefaultSizeToProgressTypesColumns(d, this);
d.setBackground(new Color(255, 255, 255));
StickerListener sl = new StickerListener(d, this);
this.addMouseMotionListener(sl);
this.addMouseListener(sl);
this.addComponentListener(new ComponentListener() {
public void componentResized(ComponentEvent e) {
setDefaultSizeToProgressTypesColumns(d,window);
}
@Override
public void componentMoved(ComponentEvent e) {}
@Override
public void componentShown(ComponentEvent e) {}
@Override
public void componentHidden(ComponentEvent e) {}
});
jtb = new JToolBar();
Edit = new JButton("Редактровать");
jtb.add(Edit);
Delete = new JButton("Удалить");
jtb.add(Delete);
Read = new JButton("Просмотреть");
jtb.add(Read);
add(jtb, BorderLayout.NORTH);
jtb.setVisible(false);
stickerToolBarActivated=false;
setVisible(true);
}
private void createMenu(Desk d)
{
JMenuBar menuBar = new JMenuBar();
JMenu DeskFile = new JMenu("Файл");
JMenuItem SaveDesk = new JMenuItem("Сохранить доску");
DeskFile.add(SaveDesk);
menuBar.add(DeskFile);
JMenu StickerOptions = new JMenu("Стикер");
JMenuItem NewSticker = new JMenuItem("Добавить стикер");
NewSticker.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e) {
d.ProgressTypes.get(0).addSticker();
setDefaultSizeToProgressTypesColumns(d, window);
d.repaint();
}
});
StickerOptions.add(NewSticker);
menuBar.add(StickerOptions);
add(menuBar, BorderLayout.NORTH);
setJMenuBar(menuBar);
}
public JToolBar getStickerToolbar() {
return jtb;
}
public static void setDefaultSizeToProgressTypesColumns(Desk d, Window window)
{
int x=0;
int y=0;
int WindowWidth = window.getWidth();
int WindowHeight = window.getHeight();
int ptCount = d.ProgressTypes.size();
for(ProgressType pt: d.ProgressTypes)
{
pt.x=x;
pt.y=y;
pt.width= WindowWidth/ptCount;
pt.height = WindowHeight;
x+=pt.width;
for(int s=0; s<pt.stickers.size(); ++s) {
pt.stickers.get(s).setWidth(pt.width);
pt.stickers.get(s).setHeight(pt.width);
pt.stickers.get(s).y=pt.height/20+pt.width*s;
pt.stickers.get(s).x=pt.x;
}
}
}
public JButton getEdit() {
return Edit;
}
}
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class Desk extends JPanel {
public ArrayList<ProgressType> ProgressTypes;
public int width;
public Desk()
{
ProgressTypes = new ArrayList<ProgressType>();
ProgressTypes.add(new ProgressType("Идеи"));
ProgressTypes.add(new ProgressType("Сделать"));
ProgressTypes.add(new ProgressType("В процессе"));
ProgressTypes.add(new ProgressType("Тестируется"));
ProgressTypes.add(new ProgressType("Готово"));
}
@Override
public void paint(Graphics g) {
super.paint(g);
for(ProgressType pt: ProgressTypes) {
pt.paint(g);
}
for(ProgressType pt: ProgressTypes)
for(Sticker s : pt.stickers)
s.paint(g);
}
}
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class ProgressType extends JPanel {
public ArrayList<Sticker> stickers;
public String name;
public int x, y, width, height;
public ProgressType(String n)
{
this.name = n;
stickers = new ArrayList<>();
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
final BasicStroke borderLine = new BasicStroke(4.0f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_ROUND, 5.0f);
g2d.setStroke(borderLine);
g2d.setColor(Color.black);
g2d.drawLine(x, y, x+width, y);
g2d.drawLine(x, y, x, y+height);
g2d.drawLine(x, y+height/20, x+width, y+height/20); //height/20 это высота шапки таблицы
g2d.drawLine(x+width, y, x+width, y+height);
}
public int findSticker(String search) {
for(int i=0; i<stickers.size(); ++i)
{
if(stickers.get(i).title.matches(search))
return i;
}
return -1;
}
public void addSticker()
{
StickerBuilder sb = new StickerBuilder();
Sticker s = sb.getSticker();
s.y=(height/20)+(width*stickers.size())+5;
stickers.add(s);
repaint();
}
public void addSticker(Sticker s)
{
for(int i=0; i<stickers.size(); ++i)
{
stickers.get(i).y=s.y=(height/20)+(width*(i+1))+5*(i+1);
}
s.y=(height/20);
stickers.add(s);
}
}
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
public class Sticker extends JPanel {
public String text;
private String Progress;
public String title;
private BufferedImage img;
public int x;
public int y;
public int width;
public int height;
public Sticker ( String text, String Progress,String title, int x, int y)
{
this.text=text;
this.Progress=Progress;
this.title = title;
this.x=x;
this.y=y;
this.width = -1;
this.height = -1;
try {
URL resource = Sticker.class.getResource("\\transparentSticker.png");
img = null;
this.img = ImageIO.read(Paths.get(resource.toURI()).toFile());
System.out.println("c");
} catch (IOException | URISyntaxException e) {
System.out.println("caught");
}
}
public void setText(String text) {
this.text = text;
}
public void setProgress(String progress) {
Progress = progress;
}
public void setTitle(String title) {
this.title = title;
}
public void setWidth(int width){
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public Sticker clone()
{
Sticker s= new Sticker(text, Progress, title, x, y);
s.setHeight(width);
s.setWidth(width);
return s;
}
@Override
public void paint(Graphics g) {
super.paint(g);
System.out.print("p");
g.drawImage(img, x, y, width-4, height, null);
String NormStr;
if(title!=null) {
NormStr = NormalizeLabel(title, g);
g.drawString(NormStr, x, y + width / 5);
}
if(text!=null) {
NormStr = NormalizeLabel(text, g);
FontMetrics fm = g.getFontMetrics(g.getFont());
int hgt = fm.getHeight();
String [] n=NormStr.split("\n");
for(int i= 0; i<n.length; ++i) {
g.drawString(n[i], x, y + width / 5 + hgt * 13 / 10 * (i + 1));
if(width / 5 + hgt * 13 / 10 * (i + 1)>=width*0.75)
{
g.drawString("...", x, y + width / 5 + hgt * 13 / 10 * (i + 1));
break;
}
}
}
}
private String NormalizeLabel(String s, Graphics g)
{
String NormalizedString = "";
String buf="";
FontMetrics fm = g.getFontMetrics(g.getFont());
int hgt= fm.getHeight();
int strw=0;
for(int i=0; i<s.length(); ++i)
{
buf+=s.charAt(i);
strw=fm.stringWidth(buf);
if(strw>=width*0.75)
{
NormalizedString+=buf;
NormalizedString+="\n";
buf="";
}
}
NormalizedString+=buf;
return NormalizedString;
}
}
import java.util.ArrayList;
public interface Builder {
void setText(String text);
void setProgress(String Progress);
void setTitle(String title);
Sticker getSticker();
}
import java.util.ArrayList;
public class StickerBuilder implements Builder{
public StickerBuilder() {
}
private String text;
private String Progress;
private String title;
public void setText(String text) {
this.text = text;
}
public void setProgress(String progress) {
Progress = progress;
}
public void setTitle(String title) {
this.title = title;
}
public Sticker getSticker()
{
return new Sticker(text, Progress, title, 0, 0);//возможно, стоит добавить функцию для х и у
}
}
import java.util.ArrayList;
import javax.swing.*;
import java.awt.*;
public class StickerChanger implements Builder {
private Sticker sticker;
public StickerChanger(Sticker sticker) {
this.sticker = sticker;
}
@Override
public void setText(String text) {
this.sticker.setText(text);
}
@Override
public void setProgress(String Progress) {
this.sticker.setProgress(Progress);
}
@Override
public void setTitle(String title) {
this.sticker.setTitle(title);
}
@Override
public Sticker getSticker() {
return null;
}
}
import javax.swing.*;
import java.awt.event.*;
import java.util.ArrayList;
public class StickerListener implements MouseMotionListener, MouseListener {
private ArrayList<ProgressType> PTs;
private boolean StickerIsBeingDragged;
private int DistanceToTheEndX;
private int DistanceToTheEndY;
private Sticker CurrentSticker;
private Desk d;
private Window window;
private boolean sd2;
private final int Y_DELTA=50;
private ActionListener del;
private ActionListener edit;
private ActionListener rd;
private StickerEditorWindow sew;
public StickerListener(Desk d, Window w)
{
this.d = d;
this.PTs=d.ProgressTypes;
this.DistanceToTheEndX=this.DistanceToTheEndY=0;
this.StickerIsBeingDragged = this.sd2=false;
this.window =w;
}
@Override
public void mouseDragged(MouseEvent e) {
if (StickerIsBeingDragged)
{
sd2=true;
CurrentSticker.x=e.getX()-DistanceToTheEndX;
CurrentSticker.y=e.getY()-DistanceToTheEndY;
System.out.println(CurrentSticker.x+" "+CurrentSticker.y+" "+e.getX()+" "+ e.getY()+" "+"dragged");
d.repaint();
}
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
boolean f = true;
if(e.getButton() == MouseEvent.BUTTON1)
for (ProgressType pt : PTs) {
for (Sticker s : pt.stickers) {
System.out.println((e.getX() >= s.x) + " " + (e.getX() <= (s.x + s.width))+ " " +
(e.getY()-Y_DELTA >= s.y ) + " " + (e.getY()-Y_DELTA <= (s.y + s.width)));
System.out.println(e.getX() + " "+ e.getY()+ " " + s.x+ " "+ s.y);
if (e.getX() >= s.x && e.getX() <= (s.x + s.width) &&
e.getY()-Y_DELTA >= s.y && e.getY()-Y_DELTA <= (s.y + s.width)) {
CurrentSticker = s;
f=false;
JToolBar jtb = window.getStickerToolbar();
jtb.setVisible(true);
System.out.println("условие работает");
window.stickerToolBarActivated = true;
setListeners(s, pt, jtb);
f = false;
//Sticker buf = (Sticker) CurrentSticker.clone();
//pt.addSticker(buf);
d.repaint();
} else {
window.getStickerToolbar().setVisible(false);
sew = null;
window.stickerToolBarActivated = false;
if(rd!=null)
{
window.Read.removeActionListener(rd);
rd = null;
}
if(del!=null)
{
window.Delete.removeActionListener(del);
del = null;
}
if(edit!=null)
{
window.Edit.removeActionListener(edit);
edit = null;
}
}
}
}
System.out.println(e.getX()+" "+ e.getY()+" "+"cliicked");
}
private void setListeners(Sticker s, ProgressType pt, JToolBar jtb) {
del = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int iRes = JOptionPane.showConfirmDialog(window, "Удалить этот стикер?", "",
JOptionPane.YES_NO_OPTION);
if (iRes == JOptionPane.YES_NO_OPTION) {
pt.stickers.remove(s);
jtb.setVisible(false);
d.repaint();
}
}
};
edit = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (sew == null) {
createStickerEditorWindow(s);
}
}
};
rd = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
StickerReadingWindow srw = new StickerReadingWindow(s);
}
};
window.Delete.addActionListener(del);
window.Edit.addActionListener(edit);
window.Read.addActionListener(rd);
}
@Override
public void mousePressed(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1)
for(ProgressType pt: PTs) {
for (Sticker s : pt.stickers) {
if (e.getX() >= s.x && e.getX() <= (s.x + s.width) &&
e.getY()-Y_DELTA >= s.y && e.getY()-Y_DELTA <= (s.y + s.width)) {
DistanceToTheEndX = e.getX()-s.x;
DistanceToTheEndY = e.getY()-s.y;
StickerIsBeingDragged = true;
CurrentSticker = s;
System.out.println(s.x+" "+s.y+" "+e.getX()+" "+ e.getY()+" "+"pressed");
}
}
}
}
private void createStickerEditorWindow(Sticker s)
{
DefaultListModel listModel = new DefaultListModel();
for (ProgressType pt: PTs)
listModel.addElement(pt.name);
sew = new StickerEditorWindow(s, listModel);
sew.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
sew=null;
d.repaint();
}
});
}
@Override
public void mouseReleased(MouseEvent e) {
if(StickerIsBeingDragged) {
if(sd2) {
System.out.println(CurrentSticker.x + " " + CurrentSticker.y + " " + e.getX() + " " + e.getY() + " " + "released");
StickerIsBeingDragged = false;
d.repaint();
if (CurrentSticker.x < 0)
CurrentSticker.x = 0;
else if (CurrentSticker.x > window.getWidth())
CurrentSticker.x = window.getWidth() - 15;
for (ProgressType pt : PTs) {
if (CurrentSticker.x >= pt.x && CurrentSticker.x < pt.x + pt.width && CurrentSticker.x >= 0) {
CurrentSticker.x = pt.x;
Sticker buf = (Sticker) CurrentSticker.clone();
pt.addSticker(buf);
}
if (pt.stickers.indexOf(CurrentSticker) != -1) {
pt.stickers.remove(CurrentSticker);
}
}
sd2=false;
d.repaint();
}
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
public class StickerEditorWindow extends JFrame {
private Sticker sticker;
private JTextField title;
private JTextArea text;
private JList ProgressTypes;
private JButton Save;
private JButton DelayTitleChanges;
private JButton DelayTextChanges;
private JButton DelayProgressTypeChanges;
private DefaultListModel listModel;
public StickerEditorWindow(Sticker s, DefaultListModel lm) {
this.sticker = s;
setSize(600,300);
setTitle("Редактировать стикер");
setAlwaysOnTop(true);
// setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(
0, 0,
1, 1,
4, 0,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
new Insets(5, 5, 5, 5),
0, 0
);
title = new JTextField("Тема");
text = new JTextArea("Введите текст");
this.listModel = lm;
ProgressTypes = new JList(listModel);
this.add(title, gbc);
++gbc.gridy;
gbc.weighty=4;
this.add(text, gbc);
this.add(new JScrollPane(text), gbc);
gbc.weighty=0;
++gbc.gridy;
this.add(ProgressTypes, gbc);
ProgressTypes.setFocusable(false);
this.add(new JScrollPane(ProgressTypes), gbc);
ProgressTypes.setVisible(true);
Save = new JButton("Cохранить");
DelayTitleChanges = new JButton("Отменить изм. темы");
DelayTextChanges = new JButton("Отменить изм. текста");
DelayProgressTypeChanges = new JButton("Отменить изм. колонки прогресса");
gbc.gridx=1;
gbc.weightx=1;
gbc.gridy = 3;
this.add(Save, gbc);
gbc.gridy = 0;
this.add(DelayTitleChanges, gbc);
gbc.gridy = 1;
gbc.weighty=4;
this.add(DelayTextChanges, gbc);
gbc.gridy = 2;
this.add(DelayProgressTypeChanges, gbc);
if(sticker.text!=null) {
text.setText(sticker.text);
}
if(sticker.title!=null)
title.setText(sticker.title);
setListeners();
setVisible(true);
}
private void setListeners()
{
StickerEditorWindow w = this;
this.Save.addActionListener(new StickerChangeListener(w, this.Save));
this.DelayProgressTypeChanges.addActionListener(new StickerChangeListener(w, this.DelayProgressTypeChanges));
this.DelayTitleChanges.addActionListener(new StickerChangeListener(w, this.DelayTitleChanges));
this.DelayTextChanges.addActionListener(new StickerChangeListener(w, this.DelayTextChanges));
}
public void SaveStickerChanges()
{
sticker.title=title.getText();
sticker.text = text.getText();
}
public void CancelTitleChanges()
{
title.setText(sticker.title);
}
public void CancelTextChanges()
{
text.setText(sticker.text);
}
}
import javax.swing.*;
import javax.swing.plaf.basic.BasicOptionPaneUI;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class StickerChangeListener implements ActionListener {
private StickerEditorWindow sew;
private JButton sender;
public StickerChangeListener(StickerEditorWindow sew, JButton sender) {
this.sew = sew;
this.sender = sender;
}
@Override
public void actionPerformed(ActionEvent e) {
if(sender.getText().equals("Cохранить")){
sew.SaveStickerChanges();
}
if(sender.getText().equals("Отменить изм. темы")){
sew.CancelTitleChanges();
}
if(sender.getText().equals("Отменить изм. текста")){
sew.CancelTextChanges();
}
if(sender.getText().equals("Отменить изм. колонки прогресса")){}
}
}
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
public class StickerReadingWindow extends JFrame{
private Sticker sticker;
private int width;
private int height;
ReadingCrutch rc;
public StickerReadingWindow(Sticker s) throws HeadlessException {
this.sticker = s;
width=height=500;
String winHeader = "";
if(sticker.title!=null)
winHeader+="Тема: "+sticker.title+ " ";
setTitle(winHeader);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JPanel jp = new JPanel();
add(jp);
Graphics g =jp.getGraphics();
setSize(width,height);
setTitle("Редактировать стикер");
setAlwaysOnTop(true);
BufferedImage img = null;
try {
URL resource = Sticker.class.getResource("\\transparentSticker.png");
img = ImageIO.read(Paths.get(resource.toURI()).toFile());
System.out.println("c");
} catch (IOException | URISyntaxException e) {
System.out.println("caught");
}
if(img!=null)
rc = new ReadingCrutch(img, sticker.text, width);
add(rc);
setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class ReadingCrutch extends JPanel {
private BufferedImage img;
private String str;
private int width;
public ReadingCrutch(BufferedImage img, String str, int w) {
this.img = img;
this.str = str;
this.width =w;
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(img, 0, 0, 450, 450, null);
g.setColor(Color.black);
String txt = str;
String [] s=txt.split(" ");
String buf= "";
String NormalizedString="";
FontMetrics fm = g.getFontMetrics(g.getFont());
int hgt= fm.getHeight();
int strw=0;
for(int i=0; i<s.length; ++i)
{
buf+=s[i]+" ";
strw=fm.stringWidth(buf);
if(strw>=width*0.75)
{
NormalizedString+=buf;
NormalizedString+="\n";
buf="";
}
}
NormalizedString+=buf;
g.setColor(Color.black);
String[] forWrite= NormalizedString.split("\n");
for(int i=0; i<forWrite.length; ++i)
{
g.drawString(forWrite[i]+" ", 0, 0 + width / 5 + hgt * 13 / 10 * (i + 1));
}
}
}
The problem is in the control flow of the StickerListener.mouseClicked()
: you search the stickers to find the one that has been clicked.
Due to the if
/ else
you reset the toolbar for every sticker that has not been clicked, meaning that your code only works if you clicked on the last sticker (in order of iteration).
Your code will work if you move the code from the else
part before the loop (so that it executes only once):
@Override
public void mouseClicked(MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON1) {
window.getStickerToolbar().setVisible(false);
sew = null;
window.stickerToolBarActivated = false;
if (rd != null) {
window.Read.removeActionListener(rd);
rd = null;
}
if (del != null) {
window.Delete.removeActionListener(del);
del = null;
}
if (edit != null) {
window.Edit.removeActionListener(edit);
edit = null;
}
for (ProgressType pt : PTs) {
for (Sticker s : pt.stickers) {
System.out.println((e.getX() >= s.x) + " " + (e.getX() <= (s.x + s.width)) + " " +
(e.getY() - Y_DELTA >= s.y) + " " + (e.getY() - Y_DELTA <= (s.y + s.width)));
System.out.println(e.getX() + " " + e.getY() + " " + s.x + " " + s.y);
if (e.getX() >= s.x && e.getX() <= (s.x + s.width) &&
e.getY() - Y_DELTA >= s.y && e.getY() - Y_DELTA <= (s.y + s.width)) {
CurrentSticker = s;
JToolBar jtb = window.getStickerToolbar();
jtb.setVisible(true);
System.out.println("условие работает");
window.stickerToolBarActivated = true;
setListeners(s, pt, jtb);
//Sticker buf = (Sticker) CurrentSticker.clone();
//pt.addSticker(buf);
d.repaint();
return;
}
}
}
}
System.out.println(e.getX()+" "+ e.getY()+" "+"cliicked");
}