2015-12-15 4 views
3

Я новичок в качелях и есть вопрос, как лучше сделать эту форму:Swing - неправильная форма граница

complicated shape

Я думал два способов

  1. для рисования правильного прямоугольника и написать пользовательскую границу?
  2. для рисования регулярного прямоугольника + составной границы (который содержит 2 или 3 границы). Но здесь мне не удается сделать границу внутри формы, возможно вообще? Что-то вроде этого: two borders figure.setBorder (BorderFactory.createCompoundBorder (BorderFactory.createMatteBor der (внешний верхний, левый, нижний, правый, цвет.WHITE), createMatteBorder (внутри сверху, слева, снизу, справа, цвет.WHITE)), где внутренняя граница маленький прямоугольник, так и снаружи большой прямоугольник - не уверен, если это возможно ???

Пожалуйста посоветуйте и представлен пример будет высоко оценен

+0

Что вы имеете в виду под "границы"? – MadProgrammer

+0

См. Также [Граница с закругленными углами и прозрачностью] (http://stackoverflow.com/questions/15025092/border-with-rounded-corners-transparency). –

+0

благодарим за ответы! – altavista23

ответ

1

вы можете использовать полигон! класс (java.awt.Polygon)

int xs = new int[]{1,2,3...7}; //your x-coordinates 
int ys = new int[]{1,2,3...7}; //your y-coordinates 
Shape irr = new Polygon(xs, ys, xs.length); 

если вы хотите использовать определенные границы вы можете использовать Graphics2D

public void paintComponent(Graphics gr){ 
    Graphics2D g2d = (Graphics2D)gr; 

    GradientPaint redToWhite = new GradientPaint(0,0,color.RED,100, 0,color.WHITE); 
    g2d.setPaint(redtowhite) 
    g2d.fill(irr); //fill special color 

    Stroke customBorder = getCustomBorder(); 
    g2d.setStroke(customBorder); 
    g2d.draw(irr); //draw 'special' borders 

} 

посмотреть на stroke and fill

отмечают, что Polygon реализует contains(double x, double y) метод, который позволяет обнаружить, если вы находитесь внутри или нет

+0

Прошу прощения, у меня нет ваших координат для очков вашей формы, вставьте их, пожалуйста, самостоятельно ... –

+0

Большое спасибо! Многоугольник - очень хороший вариант, но подумал, что мне будет легче играть с 2 или более границами (чтобы интегрировать в существующий код , который до сих пор поддерживал только прямоугольники). – altavista23

+0

вы можете использовать Graphics2D - я добавлю это в свой anwer –

1

Вы можете использовать Area, например ...

Area

public class TestPane extends JPanel { 

    public TestPane() { 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(200, 200); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g.create(); 
     Area area = new Area(new Rectangle(10, 10, getWidth() - 20, getHeight() - 20)); 
     area.subtract(new Area(new Rectangle(20, getHeight()/2, getWidth()/2, getHeight() - 10))); 
     g2d.draw(area); 
     g2d.dispose(); 
    } 

} 

Вы определяете пользовательские формы ...

Path2D

public class TestPane extends JPanel { 

    public TestPane() { 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(200, 200); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g.create(); 
     Path2D path = new Path2D.Float(); 
     path.moveTo(10, 10); 
     path.lineTo(getWidth() - 20, 10); 
     path.lineTo(getWidth() - 20, getHeight() - 20); 
     path.lineTo(getWidth()/2, getHeight() - 20); 
     path.lineTo(getWidth()/2, getHeight()/2); 
     path.lineTo(20, getHeight()/2); 
     path.lineTo(20, getHeight() - 20); 
     path.lineTo(10, getHeight() - 20); 
     path.closePath(); 
     g2d.draw(path); 
     g2d.dispose(); 
    } 

} 

На самом деле писать пользовательские границы будет очень, очень трудно, из-за неправильной формы стиля, то где компоненты на самом деле должны содержаться?

Можно было бы создать две или несколько границ, которые затем могут быть разложены так, что появился как один

См Working with Geometry для более подробной информации

Обновленные с Border например ...

Получение работы Border на самом деле намного сложнее, так как ожидается, что внутренняя область границы будет прямоугольной.

Основываясь на комплексной форме, которую вы предоставили, одним из решений было бы создать две границы, левый и правый бурильщики, которые будут заботиться о создании «безопасной» области для компонентов, которые будут выложены внутри, например :

public class LeftBorder implements Border { 

    private int offset; 

    public LeftBorder(int offset) { 
     this.offset = offset; 
    } 

    @Override 
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 
     Path2D path = new Path2D.Float(); 

     int xOffset = x + offset; 
     int yOffset = y + offset; 

     width -= offset; 
     height -= offset * 2; 

     float gap = width * 0.1f; 

     path.moveTo(xOffset, yOffset); 
     path.lineTo(xOffset + width, yOffset); 
     path.moveTo(xOffset, yOffset); 

     path.lineTo(xOffset, yOffset + height); 
     path.lineTo(xOffset + gap, yOffset + height); 
     path.lineTo(xOffset + gap, yOffset + (height - (height/2))); 
     path.lineTo(xOffset + width, yOffset + (height - (height/2))); 

     ((Graphics2D)g).draw(path); 
    } 

    @Override 
    public Insets getBorderInsets(Component c) { 

     int height = c.getHeight(); 
     height -= (height/2); 

     System.out.println(height); 
     return new Insets(offset + 4, offset + 4, height + 4, 0); 
    } 

    @Override 
    public boolean isBorderOpaque() { 
     return false; 
    } 

} 

public class RightBorder implements Border { 

    private int offset; 

    public RightBorder(int offset) { 
     this.offset = offset; 
    } 

    @Override 
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 
     Path2D path = new Path2D.Float(); 

     int xOffset = x; 
     int yOffset = y + offset; 

     width -= offset; 
     height -= offset * 2; 

     path.moveTo(xOffset, yOffset); 
     path.lineTo(xOffset + width, yOffset); 
     path.lineTo(xOffset + width, yOffset + height); 
     path.lineTo(xOffset, yOffset + height); 

     path.lineTo(xOffset, yOffset + (height - (height/2))); 

     ((Graphics2D)g).draw(path); 
    } 

    @Override 
    public Insets getBorderInsets(Component c) { 

     return new Insets(offset + 4, 0, offset + 4, offset + 4); 
    } 

    @Override 
    public boolean isBorderOpaque() { 
     return false; 
    } 

} 

Это потребовало бы вам предоставить, по меньшей мере две панели одинаковой высоты, например:

Example layout

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Insets; 
import java.awt.geom.Path2D; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.Border; 

public class Main { 

    public static void main(String args[]) { 
     new Main(); 
    } 

    public Main() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new GridBagLayout()); 
       frame.add(new LeftPane()); 
       frame.add(new RightPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class RightPane extends JPanel { 

     public RightPane() { 
      setBorder(new RightBorder(10)); 
      setLayout(new GridBagLayout()); 
      add(new JLabel("Righty")); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

    } 

    public class LeftPane extends JPanel { 

     public LeftPane() { 
      setBorder(new LeftBorder(10)); 
      setLayout(new GridBagLayout()); 
      add(new JLabel("Lefty")); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

    } 

} 

Это также будет полезным для менеджера компоновки, который мог бы компоновать два компонента рядом друг с другом.

+0

Спасибо большое! Я думал об этом варианте, чтобы получить от JPanel, но думал, что wil Мне будет легче узнать, как играть с 2 или более границами (для интеграции в существующий код, который до сих пор поддерживал только прямоугольники). – altavista23

+0

Возможно, можно создать две или более границы, которые затем можно было бы выложить так, чтобы появилось как одно - да, это то, что я хотел (я добавил к вопросу), но не удалось. Эта фигура наследуется от Jpanel и реализована как прямоугольная, с множеством логики, которую я хотел сохранить как есть, поэтому игра с границей я вижу лучший вариант. Родительский контейнер рисунка также является JPanel. – altavista23

+0

отлично, спасибо большое! – altavista23

1

Посмотрите на Java 2D API. Это помогает вам рисовать сложные формы.

E.g.

class IrregularShape extends JComponent { 

    private int strokeWidth; 

    IrregularShape(int strokeWidth){ 
     this.strokeWidth = strokeWidth; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     Graphics2D newGraphics = (Graphics2D) g.create(); 

     Insets borderInsets = new Insets(0, 0, 0, 0); 
     Border border = getBorder(); 
     if (border != null) { 
      borderInsets = border.getBorderInsets(this); 
     } 

     BasicStroke basicStroke = new BasicStroke(strokeWidth); 
     newGraphics.setStroke(basicStroke); 

     int x = getX() + borderInsets.left + strokeWidth; 
     int y = getY() + borderInsets.top + strokeWidth; 
     int width = getWidth() - x - borderInsets.right - strokeWidth; 
     int height = getHeight() - y - borderInsets.bottom - strokeWidth; 

     Double outterRactangleDouble = new Rectangle2D.Double(x, y, width, height); 

     Area outterRectangle = new Area(outterRactangleDouble); 

     Area innerRectangle = new Area(outterRactangleDouble); 
     AffineTransform affineTransform = new AffineTransform(); 
     affineTransform.scale(0.5, 0.5); 
     affineTransform.translate(x + width * 0.10, y + height * 1.2); 

     innerRectangle.transform(affineTransform); 
     outterRectangle.subtract(innerRectangle); 
     newGraphics.draw(outterRectangle); 

    } 

} 

public class MainFrame { 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("Irregular Shape"); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     Container contentPane = frame.getContentPane(); 
     contentPane.add(new IrregularShape(3)); 

     frame.setSize(640, 150); 

     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

} 

Результат enter image description here

и это также изменяемого размера

enter image description here

+0

Спасибо большое!Я подумал, что мне будет легче узнать, что вы играете с двумя или более границами (чтобы интегрировать в существующий код, который поддерживал только прямоугольники до сих пор, я добавил больше фото в вопрос). Но если мне это не удастся, я буду использовать ваша идея, которая потребует большей вставки в существующий код, спасибо! – altavista23

0

В дополнение к моему первому ответу https://stackoverflow.com/a/34287251/974186

Вы также можете реализовать его в качестве границы.

class IrregularBorder implements Border { 

    private int thickness; 

    public IrregularBorder(int thickness) { 
     this.thickness = thickness; 
    } 

    @Override 
    public void paintBorder(Component c, Graphics g, int x, int y, int width, 
      int height) { 
     Graphics2D graphics2d = (Graphics2D) g; 

     BasicStroke basicStroke = new BasicStroke(thickness); 
     graphics2d.setStroke(basicStroke); 

     int halfThickness = thickness/2; 
     Double outterRactangleDouble = new Rectangle2D.Double(
       x + halfThickness, y + halfThickness, width - thickness, 
       height - thickness); 

     Area outterRectangle = new Area(outterRactangleDouble); 

     Area innerRectangle = computeInnerRect(x, y, width, height, 
       outterRactangleDouble); 
     outterRectangle.subtract(innerRectangle); 
     graphics2d.draw(outterRectangle); 

    } 

    private Area computeInnerRect(int x, int y, int width, int height, 
      Double outterRactangleDouble) { 
     Area innerRectangle = new Area(outterRactangleDouble); 
     AffineTransform affineTransform = new AffineTransform(); 
     affineTransform.scale(0.5, 0.5); 
     affineTransform.translate(x + width * 0.10, y + height * 1.2); 

     innerRectangle.transform(affineTransform); 
     return innerRectangle; 
    } 

    @Override 
    public Insets getBorderInsets(Component c) { 
     int left = (int) (thickness + (c.getWidth() * 0.6)); 
     return new Insets(thickness, left, thickness, thickness); 
    } 

    @Override 
    public boolean isBorderOpaque() { 
     return true; 
    } 

} 

и использовать его как обычный

public class MainFrame { 

    public static void main(String[] args) { 
     JFrame frame = new JFrame("Irregular Shape"); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     Container contentPane = frame.getContentPane(); 

     JPanel mainPanel = new JPanel(new BorderLayout()); 
     mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 
     contentPane.add(mainPanel); 

     JPanel irregularShapeBorderedPanel = new JPanel(new BorderLayout()); 
     irregularShapeBorderedPanel.add(new JButton("Button"), 
       BorderLayout.CENTER); 
     irregularShapeBorderedPanel.setBorder(new IrregularBorder(2)); 

     mainPanel.add(irregularShapeBorderedPanel); 

     frame.setSize(640, 150); 

     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

} 

enter image description here

+0

Большое спасибо за помощь !! Я попробую этот код с границами сейчас! – altavista23

Смежные вопросы