2009-12-12 17 views
8

यह एक known bug/issue कि जीटीके में एक लेबल गतिशील आकार नहीं बदलेंगे जब मूल परिवर्तनों है। यह उन वास्तव में कष्टप्रद छोटे विवरणों में से एक है, और यदि संभव हो तो मैं इसके आसपास हैक करना चाहता हूं।PyGTK: गतिशील लेबल लपेटकर

मैं 16 software पर दृष्टिकोण पीछा किया, लेकिन त्याग के अनुसार आपको तो यह छोटे आकार नहीं कर सकते हैं। तो मैंने टिप्पणियों में से एक में उल्लिखित एक चाल का प्रयास किया (set_size_request सिग्नल कॉलबैक में कॉल), लेकिन इसके परिणामस्वरूप कुछ प्रकार के अनंत लूप (इसे आज़माएं और देखें)।

किसी को भी किसी भी अन्य विचारों है?

(तुम सिर्फ कॉल की अवधि के लिए संकेत नहीं रोक सकते हैं, के बाद से के रूप में print बयानों से संकेत मिलता है लगता है, समस्या समारोह छोड़ दिया है के बाद शुरू होता है।)

कोड के नीचे है। यदि आप इसे चलाते हैं तो आप देख सकते हैं कि मेरा क्या मतलब है और विंडो को बड़ा आकार देने का प्रयास करें और फिर छोटा। (यदि आप मूल समस्या देखना चाहते हैं, तो "आकार-आवंटित सिग्नल से कनेक्ट करें" के बाद लाइन को टिप्पणी करें, इसे चलाएं, और विंडो को बड़ा आकार दें।)

ग्लेड फ़ाइल ("example.glade"):

<?xml version="1.0"?> 
<glade-interface> 
    <!-- interface-requires gtk+ 2.16 --> 
    <!-- interface-naming-policy project-wide --> 
    <widget class="GtkWindow" id="window1"> 
    <property name="visible">True</property> 
    <signal name="destroy" handler="on_destroy"/> 
    <child> 
     <widget class="GtkLabel" id="label1"> 
     <property name="visible">True</property> 
     <property name="label" translatable="yes">In publishing and graphic design, lorem ipsum[p][1][2] is the name given to commonly used placeholder text (filler text) to demonstrate the graphic elements of a document or visual presentation, such as font, typography, and layout. The lorem ipsum text, which is typically a nonsensical list of semi-Latin words, is a hacked version of a Latin text by Cicero, with words/letters omitted and others inserted, but not proper Latin[1][2] (see below: History and discovery). The closest English translation would be "pain itself" (dolorem = pain, grief, misery, suffering; ipsum = itself).</property> 
     <property name="wrap">True</property> 
     </widget> 
    </child> 
    </widget> 
</glade-interface> 

अजगर कोड:

#!/usr/bin/python 

import pygtk 
import gobject 
import gtk.glade 

def wrapped_label_hack(gtklabel, allocation): 
    print "In wrapped_label_hack" 
    gtklabel.set_size_request(allocation.width, -1) 
    # If you uncomment this, we get INFINITE LOOPING! 
    # gtklabel.set_size_request(-1, -1) 
    print "Leaving wrapped_label_hack" 

class ExampleGTK: 

    def __init__(self, filename): 
     self.tree = gtk.glade.XML(filename, "window1", "Example") 
     self.id = "window1" 
     self.tree.signal_autoconnect(self) 

     # Connect to the size-allocate signal 
     self.get_widget("label1").connect("size-allocate", wrapped_label_hack) 

    def on_destroy(self, widget): 
     self.close() 

    def get_widget(self, id): 
     return self.tree.get_widget(id) 

    def close(self): 
     window = self.get_widget(self.id) 
     if window is not None: 
      window.destroy() 
     gtk.main_quit() 

if __name__ == "__main__": 
    window = ExampleGTK("example.glade") 
    gtk.main() 
+0

और भी आसान हो सकता है: अंत में मेरी पोस्ट देखें। http://stackoverflow.com/questions/2014804/word-wrap-in-pygtk-treeview –

उत्तर

3

VMware के libview एक विजेट WrapLabel कहा जाता है जो आप क्या चाहते हैं क्या करना चाहिए है, लेकिन यह सी में है ++। एक पायथन अनुवाद Meld repository में उपलब्ध है (busybox.py से अलग)।

+0

वाह, मैं * कभी * यह नहीं मिला होगा। धन्यवाद। मैंने इसे मैन्युअल रूप से ग्लैड में एक HBox बनाकर जोड़ा और कोड को __init__ में डालने के लिए जोड़ दिया। (यदि आप वास्तव में मेहनती हैं तो आप इसके लिए एक ग्लैड कैटलॉग फ़ाइल बना सकते हैं ...)। मुझे यह महसूस करने के लिए लगभग आधे घंटे का समय लगा कि मुझे लेबल जोड़ने के बाद एचबीओक्स पर "show_all()" का उपयोग करने की आवश्यकता है, इसलिए मुझे आशा है कि यह टिप्पणी किसी और को बचाएगी जो परेशानी है ... – detly

2

आप इस का उपयोग कर सकते हैं। निश्चित नहीं है कि यह मूल रूप से कहां से आया था। अपने लेबल बनाएं और फिर label_set_autowrap फोन (लेबल) आकार बदलने के लिए

def label_set_autowrap(widget): 
    "Make labels automatically re-wrap if their containers are resized. Accepts label or container widgets." 
    # For this to work the label in the glade file must be set to wrap on words. 
    if isinstance(widget, gtk.Container): 
     children = widget.get_children() 
     for i in xrange(len(children)): 
      label_set_autowrap(children[i]) 
    elif isinstance(widget, gtk.Label) and widget.get_line_wrap(): 
     widget.connect_after("size-allocate", _label_size_allocate) 


def _label_size_allocate(widget, allocation): 
    "Callback which re-allocates the size of a label." 
    layout = widget.get_layout() 
    lw_old, lh_old = layout.get_size() 
    # fixed width labels 
    if lw_old/pango.SCALE == allocation.width: 
     return 
    # set wrap width to the pango.Layout of the labels 
    layout.set_width(allocation.width * pango.SCALE) 
    lw, lh = layout.get_size() # lw is unused. 
    if lh_old != lh: 
     widget.set_size_request(-1, lh/pango.SCALE) 
+0

अच्छी चीजें, लेकिन किसी कारण से लेबल रैपिंग को बनाए रखने वाली एक पंक्ति पर टेक्स्ट प्रदर्शित करने के लिए काफी बड़ा है, इसलिए सभी लेबल 'y align "मान 0 पर सेट होना चाहिए, अन्यथा लेबल लेबल के अंदर पाठ गायब हो जाएगा ... –

3

उदाहरण और लेबल गतिशील लपेट:

संपादित करें:

import gtk 

class DynamicLabel(gtk.Window): 
    def __init__(self): 
     gtk.Window.__init__(self) 

     self.set_title("Dynamic Label") 
     self.set_size_request(1, 1) 
     self.set_default_size(300,300) 
     self.set_position(gtk.WIN_POS_CENTER) 

     l = gtk.Label("Dynamic Label" * 10) 
     l.set_line_wrap(True) 
     l.connect("size-allocate", self.size_request) 

     vbox = gtk.VBox(False, 2) 
     vbox.pack_start(l, False, False, 0) 

     self.add(vbox) 
     self.connect("destroy", gtk.main_quit) 
     self.show_all() 

    def size_request(self, l, s): 
     l.set_size_request(s.width -1, -1) 

DynamicLabel() 
gtk.main() 
+0

इसे बनाने का प्रयास करें 300x300 से छोटा ... – detly

+0

@detly: किसी भी आकार में काम करता है। – killown

+0

@ किलाउन - उस कोड को चलाने के रूप में, इसे आकार बदलना असंभव है * गतिशील रूप से * 300x300 से नीचे, है ना? यह निश्चित रूप से यहां मामला है। – detly

4

यहाँ killown के समाधान के एक पंक्ति भिन्नता है:

label.connect('size-allocate', lambda label, size: label.set_size_request(size.width - 1, -1)) 

ऊपर यकीन है कि लेबल चौड़ाई आवंटित टी पर ले जाता कर देगा ओ, तो शब्द-रैपिंग खुश है।

सुनिश्चित नहीं हैं कि क्यों वहाँ एक "-1" चौड़ाई के लिए, लेकिन यह हानिरहित लगता है!

+0

से छोटी काम करेगा दूसरी पंक्ति जोड़ें ... label.connect_after ("एहसास", लैम्ब्डा लेबल: label.set_size_request (चौड़ाई = -1, ऊंचाई = -1)) ... इसे प्रारंभ में आकार को ठीक से बनाने के लिए कंटेनरों और/या स्क्रॉल की कुछ विन्यास में ड्राइंग विन्डोज़ – Dave

1

जीटीके 3 में, यह स्वचालित रूप से ऊंचाई के लिए चौड़ाई और चौड़ाई के लिए ऊंचाई आकार अनुरोध का उपयोग कर किया जाता है।

1

मैं सिर्फ यह साझा करना चाहता था कि मैंने wraplabel.py का उपयोग करके पीईजीटीके और ग्लैड -3 के साथ काई का समाधान कैसे किया।

मैं ग्लैड कैटलॉग को ग्लैड में लपेटने के लिए संशोधित नहीं करना चाहता था और मुझे यकीन नहीं है कि यह एक पीईजीटीके घटक के साथ काम करेगा या नहीं। हालांकि, gtk.Bilder() में कॉल करने से पहले पाइथन पर्यावरण में WrapLabel कक्षा डालकर मुझे आश्चर्य हुआ कि यह कक्षा को एक घटक के रूप में लोड करेगा।

तो अब एकमात्र समस्या WrapLabels को ग्लैड फ़ाइल में प्राप्त करना था। सबसे पहले मैंने उन सभी लेबलों के नाम बदल दिए जिन्हें मैं wlabel ### पर लपेटना चाहता था, जहां ### कुछ संख्या है। तब मैं वर्गों को बदलने के लिए एक एसईडी अभिव्यक्ति करते थे, लेकिन बाद से मैं निर्माण प्रणाली के लिए अतिरिक्त संसाधन जोड़ने के लिए नहीं करना चाहता था मैं अजगर में निम्नलिखित जोड़ने समाप्त हो गया: मुझे यकीन है कि वहाँ और अधिक सुरुचिपूर्ण हैं हूँ

import re 
import gtk 
from wraplabel import WrapLabel 

. . . 

# Filter glade 
glade = open(filename, 'r').read() 
glade = re.subn('class="GtkLabel" id="wlabel', 
       'class="WrapLabel" id="wlabel', glade)[0] 

# Build GUI 
builder = gtk.Builder() 
builder.add_from_string(glade) 

प्रतिस्थापन करने के तरीके लेकिन यह अच्छी तरह से काम किया। हालांकि, मैंने पाया कि मुझे एक और समस्या थी। जब मैंने लपेटे हुए लेबल के साथ संवाद में से एक खोला तो कुछ पाठ दिखाई नहीं दे रहा था। तब जब मैंने खिड़की के साथ खिड़की का आकार बदल दिया, यहां तक ​​कि थोड़ा सा, सब कुछ जगह में फंस जाएगा। शुरुआती होने पर कुछ लेबलों को सही आकार क्यों नहीं मिल रहे थे। मैंने इसे एक और काम के साथ तय किया। जब से एक संवाद खोलने मैं इस कोड चलाएँ:

def open_dialog(self, dialog): 
    # Hack to make WrapLabel work 
    dims = dialog.get_size() 
    dialog.resize(dims[0] + 1, dims[1] + 1) 
    dialog.present() 
    dialog.resize(*dims) 

यह सिर्फ आकार एक बिंदु बहुत बड़ा सेट, खिड़की प्रस्तुत करता है और उसके बाद सही आकार के लिए रीसेट करता है। इस तरह WrapLabels संवाद लेआउट पूरा होने के बाद आकार बदलने का संकेत प्राप्त करें।

अभी भी एक छोटी सी गड़बड़ी है। जब आप कभी-कभी संवाद खोलते हैं तो आप टेक्स्ट स्नैपिंग को स्थान पर देख सकते हैं। अन्यथा, ऐसा लगता है कि यह काम करता है।

नोट 1) सभी बुला label.set_size_request (size.width के रूपांतरों - 1, -1) पर आकार आवंटित जीयूआई मेरे लिए हवालात के कारण होता है। शायद मूल विजेट पर निर्भर करता है।

नोट 2) एक अन्य समाधान टेक्स्ट व्यू का उपयोग करना और संपादन, कर्सर और संवेदनशीलता अक्षम करना है। हालांकि, टेक्स्ट व्यूज़ पृष्ठभूमि की तुलना में एक अलग रंग है जो जीटीके विषयों के चेहरे में ठीक करना मुश्किल है। इस समाधान के साथ दूसरी समस्या यह है कि TextViews माउस स्क्रॉल घटनाओं को कैप्चर करता है। यह माउस को इन टेक्स्ट व्यू के साथ एक बॉक्स को स्क्रॉल करता है जो बहुत ही अनियमित है। मैंने माउस स्क्रॉल समस्या को हल करने के लिए कई चीजों की कोशिश की लेकिन कभी इसे समझ नहीं लिया। अन्यथा TextViews का उपयोग कर काम करता है। तो आप इस पर विचार कर सकते हैं यदि आपके टेक्स्ट लेबल स्क्रॉल फलक के अंदर नहीं हैं और WrapLabel समाधान आपके लिए काम नहीं करता है।

0

मैं कोड है कि अन्य उत्तर में था एक कॉलबैक कि थोड़ा बेहतर व्यवहार किया पाने के लिए संशोधित किया है:

def on_label_size_allocate(self, label, allocation, *args): 
    """ Callback that re-allocates the size of a label to improve word wrap. """ 
    layout = label.get_layout() 
    layout.set_width((allocation.width-20) * pango.SCALE) 
    _, lh = layout.get_pixel_size() 
    label.set_size_request(-1, lh+6) 

-20 और +6 संख्या परीक्षण और त्रुटि के द्वारा प्राप्त किया गया। विजेट्स में कहीं से उन्हें प्राप्त करना अच्छा लगेगा, लेकिन मुझे विजेट्स से कोई रिश्ते नहीं मिला। इससे लेबल बढ़ने और घटने में दोनों का आकार बदल जाता है और लाइनों काटा नहीं जाता है।

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