2012-02-09 16 views
6

मैं एक पैनल जहां मैं कई मिनी पैनलों, पक्ष-साथ, विभिन्न आकारों और रंगों के साथ जगह है पर कब्जा करने के खिंचाव नहीं है, और वे पूरे माता पिता पैनल (क्षैतिज) ले लेना चाहिए।JPanels पूरी तरह से उपलब्ध स्थान

इसके लिए मैं BoxLayout (मूल पैनल के लिए) BorderLayout का उपयोग करें, और एक उप पैनल जहां मैं सभी मिनी पैनलों (नीचे दिए गए कोड को देखें) जगह के लिए। यह काम करता है और आकार बदलने और सबकुछ ठीक से व्यवहार करता है। हालांकि, चूंकि मिनी-पैनलों की संख्या बड़ी हो जाती है, इसलिए एक अजीब व्यवहार होता है: मूल स्थान के अंत में खाली स्थान दिखाई देता है।

enter image description here

मुझे लगता है कि मैंने पाया कि इस लेआउट प्रबंधकों में एक streching बग है, क्योंकि आदेश में पैनलों strech करने में, लेआउट प्रबंधक प्रत्येक मिनी पैनल के लिए एक एकल पिक्सेल जोड़ने के लिए कोशिश करता है। हालांकि, जब मिनी-पैनलों की संख्या बड़ी होती है, तो प्रत्येक के लिए एक पिक्सेल जोड़ना परिणामस्वरूप कई पिक्सल जोड़ता है और माता-पिता के आकार से आगे जा रहा है। इस प्रकार, लेआउट मैनेजर किसी भी मिनी-पैनल में किसी भी पिक्सल को नहीं जोड़ता है, जिसके परिणामस्वरूप रिक्त स्थान होता है। मैं इस व्यवहार से कैसे बच करते (चल रहा है, और खिड़की streching, समस्या को समझने की कोशिश)

package com.myPackage; 

import java.awt.*; 
import java.util.Vector; 
import javax.swing.BorderFactory; 
import javax.swing.BoxLayout; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class ColoredPanels extends JPanel 
{ 
    /* Content information. */ 
    private Vector<Integer> partitions; 
    private Vector<Color> colors; 

    /* Panel where the content panels will go. */ 
    private JPanel contentHolder; 

    private final int defaultHeight = 20; 

    public ColoredPanels(Vector<Integer> partitions, Vector<Color> colors) 
    { 
     assert partitions != null; 
     assert !partitions.isEmpty(); 
     assert colors != null; 
     assert !colors.isEmpty(); 
     assert colors.size() == partitions.size(); 

     this.partitions = partitions; 
     this.colors = colors; 

     /* Set layout manager. */ 
     setLayout(new BorderLayout()); 

     /* Create the content holder. */ 
     contentHolder = new JPanel(); 
     contentHolder.setLayout(new BoxLayout(contentHolder, BoxLayout.X_AXIS)); 
     this.add(contentHolder, BorderLayout.NORTH); 

     /* Fill content holder with colored panels. */ 
     createPanels(); 
    } 

    private void createPanels() 
    { 
     assert partitions != null; 
     assert !partitions.isEmpty(); 
     assert colors != null; 
     assert !colors.isEmpty(); 
     assert colors.size() == partitions.size(); 

     for (int i = 0; i < partitions.size(); i++) 
     { 
      JPanel newPanel = new JPanel(); 
      newPanel.setBackground(colors.get(i)); 
      newPanel.setPreferredSize(new Dimension(partitions.get(i), defaultHeight)); 
      newPanel.setMinimumSize(new Dimension(1, defaultHeight)); 
      contentHolder.add(newPanel); 
     } 
    } 

    public static void main(String[] in) 
    { 
     Vector<Integer> sizes = new Vector<Integer>(); 
     Vector<Color> cols = new Vector<Color>(); 

     /* Make 100 random sizes, and use two colors. */ 
     for (int i = 0; i < 100; i++) 
     { 
      int size = (int)Math.round(1 + Math.random() * 10); 
      sizes.add(size); 
      cols.add((i%2 == 0)? Color.red : Color.green); 
     } 

     ColoredPanels panels = new ColoredPanels(sizes, cols); 
     panels.setBorder(BorderFactory.createLineBorder(Color.yellow, 1)); 

     JFrame newFrame = new JFrame(); 
     newFrame.getContentPane().add(panels); 
     newFrame.pack(); 
     newFrame.setVisible(true); 
    } 
} 

:

यहाँ मेरी SSCCE है? मैं चाहता हूं कि मेरे पैनल पूरे कंटेनर पर कब्जा कर लें।

संपादित करें: मिनी पैनलों का उद्देश्य माउस श्रोताओं के लिए (एक बार यह हल हो गया है) का इरादा है। इस प्रकार, पेंटिंग समाधान दुर्भाग्य से बचने योग्य हैं।

+3

बहुत अच्छा SSCCE +1 – mKorbel

+0

दिलचस्प ... आप क्या होने के लिए _want_ करते हैं? सबसे आसान (संभवत: नहीं सबसे अच्छा :-) तरह से बाहर पिछले करने के लिए सभी गोलाई स्थान देने के लिए ... – kleopatra

+0

मैं मिनी पैनल पूरी तरह से उपलब्ध स्थान को भरने के लिए चाहते हो जाएगा। आखिरी तक शेष देना एक विकल्प नहीं है, क्योंकि विभाजन आकार-अनुपात का सम्मान किया जाना चाहिए। – Anoyz

उत्तर

3

लेआउट समस्याओं से ... LayoutManagers :-) एक नहीं है कि तुम क्या यह करने के लिए चाहते हैं, व्यवहार आप चाहते हैं को लागू करने से हल कर रहे हैं।

तो कोर BoxLayout बस त्रुटियों, उपवर्ग गोलाई और यह उन पिक्सल रूप में की जरूरत को वितरित करने के लिए कारण पिक्सल पर ध्यान नहीं देता है। एक बहुत ही कच्चा त्वरित उदाहरण:

public static class XBoxLayout extends BoxLayout { 

    enum Strategy { 
     NONE, 
     STRETCH_LAST, 
     DISTRUBUTE 
    } 

    private Strategy strategy; 

    public XBoxLayout(Container target, int axis, Strategy strategy) { 
     super(target, axis); 
     this.strategy = strategy; 
    } 


    @Override 
    public void layoutContainer(Container target) { 
     super.layoutContainer(target); 
     if (Strategy.NONE == strategy) return; 
     Insets targetInsets = target.getInsets(); 
     int targetSize = target.getWidth() - targetInsets.left - targetInsets.right; 
     int childSum = 0; 
     for (Component child : target.getComponents()) { 
      childSum += child.getWidth(); 
     } 
     if (targetSize > childSum) { 
      int excess = targetSize - childSum; 
      distribute(target, excess); 
     } 
    } 


    private void distribute(Container target, int excess) { 
     System.out.println("childCount/rounding excess " + target.getComponentCount() + "/" + excess); 
     if (Strategy.STRETCH_LAST == strategy) { 
      Component lastChild = target.getComponent(target 
        .getComponentCount() - 1); 
      lastChild.setSize(lastChild.getWidth() + excess, 
        lastChild.getHeight()); 
     } else { 
      int firstToDistribute = target.getComponentCount() - excess; 
      int summedOffset = 0; 
      for(int index = firstToDistribute; index < target.getComponentCount(); index++) { 
       Component child = target.getComponent(index); 
       Rectangle bounds = child.getBounds(); 
       bounds.x += summedOffset++; 
       bounds.width += 1; 
       child.setBounds(bounds); 
      } 
     } 
    } 

} 
+0

आपकी मदद के लिए धन्यवाद। यह एक व्यवहार्य समाधान की तरह दिखता है, और मैं लेआउट प्रबंधकों से जुड़े कुछ की तलाश में था। कोड ऐसा नहीं लगता है कि यह घटक आकार अनुपात (एक दूसरे के संबंध में) का सम्मान करता है, यहां तक ​​कि वितरण रणनीति के साथ भी, लेकिन मुझे बिंदु मिल गया, और उन पंक्तियों में कुछ लागू करने का प्रयास करेगा। – Anoyz

+0

मैं इस पर दूसरा जा रहा हूं - जब आपको इस तरह के कस्टम व्यवहार की ज़रूरत है, तो अपना खुद का लेआउट मैनेजर करना दर्दनाक नहीं है और आप इसे अपने विशिष्ट उपयोग-मामले के लिए अनुकूलित कर सकते हैं। –

+0

@ एनोयज़ एकल पिक्सल वितरित करना है .. रणनीति का विषय :-) जो कुछ भी आपको चाहिए, उसे लागू करें, दिन के अंत में यह वास्तविक/pref/जो भी आकार के समान आनुपातिक नहीं होगा – kleopatra

2

दो विकल्प मैं के बारे में सोच सकते हैं:

  1. एक paintComponent(...) विधि, जो सभी क्षेत्रों पेंट है कि एक कस्टम घटक है, और जब खिड़की का आकार बदलने पर यह उनके के अनुसार स्केलिंग जबकि क्षेत्रों फिर से रंगना होगा नई चौड़ाई की जानकारी।

  2. एक छवि को पेंट रंगीन क्षेत्रों एक बार, और फिर उस रंग, और फिट करने के लिए छवि rescale जब खिड़की आकार दिया जाता है।

+0

सहायता के लिए धन्यवाद। मैं मिनी श्रोताओं को माउस श्रोताओं को जोड़ने का इरादा रखता हूं। अगर मैं पेंटिंग रणनीति का उपयोग करता हूं, तो मैं यह कैसे कर सकता हूं? – Anoyz

+0

श्रोता को अंतर्निहित घटक में जोड़ना आवश्यक होगा (उदा।एक पैनल), फिर पैनल के स्केल आकार से सह समन्वय को वापस स्केल करें। –

+0

क्या लेआउट के साथ कोई आसान समाधान नहीं है? – Anoyz

1

मैं एक बार शतरंज के लिए ग्रिडलाउट का उपयोग करते समय इस समस्या में भाग गया। मेरा समाधान ग्रिडलाउट को विस्तारित करना और फ्लोटिंग पॉइंट परिशुद्धता के साथ लेआउट की गणना करना था।

+0

क्या आप उस समाधान के लिए अतिरिक्त जानकारी दे सकते हैं? – Anoyz

संबंधित मुद्दे