Re: Invisible GtkImage



On Wed, Jun 26, 2013 at 2:51 PM, Kip Warner <kip thevertigo com> wrote:
On Mon, 2013-06-24 at 13:56 -0700, Andrew Potter wrote:
So two questions now I have for you, if you don't mind. The first is a
problem with clipping, the same one I experienced a few days ago. Note
the assistant button widgets at the bottom of the assistant.

        Implementation:
        <http://pastebin.com/ynsQFTzU>

Please show the code that deals with the TextView and ScrolledWindow.
The clipping is almost certainly due to setting the minimum size on
either the TextView, or the GtkBox the two are contained in. I have
example GtkAssistant code at the bottom of this email that does not
exhibit this issue until extraordinarily small window sizes.

The second is just a request for clarification on the min() calculation
in your do_draw() override. I'd just like to better understand what that
calculation is attempting to do.

When scaling an image, both its height and width are changing. In
order to fit the allocated rectangle without clipping, one must figure
out which dimension is smallest (normalized to the aspect ratio). For
example, if a 200x100 image is allocated 200x50, the allocation is
height-limited and the image must be scaled to 100x50. OTOH if
allocated 100x100, the image is width-limited and must be scaled to
100x50.

... Hopefully now if anyone else in the future wants to do
something similar with an image in Gtk+, they'll manage to find this
thread. Actually, it might even be worth adding on the FAQ.

I'm getting motivated to work on a patch to GtkImage to add scaling support...

-------------

Below is an example program with ScalableImage in a GtkAssistant.

Example 1, start up:
http://i.imgur.com/ZdqwUZG.jpg

Example 2, Resized to less height. Notice the TextView/ScrolledWindow
had plenty of space to "give up" because it has no minimum height
http://i.imgur.com/wTN5rY9.jpg

Example 3, Clipping occurs at this very small size due to minimum size
on the ScalableImage as well as the ScrolledWindow/TextView
http://i.imgur.com/EAzFYOG.jpg

Example 4, ScalableImage is modified to return a 0 minimum size in
get_preferred_height_for_width(). This means that at very small
heights the image will not have enough space to fill the allocated
width, allowing the other widgets get some space in this corner case.
http://i.imgur.com/ZrOPt75.jpg

It is your choice whether or not to allow your header image to become
smaller when the window is pressured for height.

#!/usr/bin/python
# coding=UTF-8
from gi.repository import Gtk, Gdk, GdkPixbuf

class ScalableImage(Gtk.DrawingArea):
    def __init__(self, filename):
        super(ScalableImage, self).__init__()
        self.pb = GdkPixbuf.Pixbuf.new_from_file(filename)

    def do_get_preferred_width(self):
        pw = self.pb.get_width()
        return (0, pw)

    def do_get_preferred_height(self):
        ph = self.pb.get_height()
        return (0, ph)

    def do_get_preferred_height_for_width(self, width):
        ph = width / self.get_aspect_ratio()
        return (0, ph)

    def do_get_request_mode(self):
        return Gtk.SizeRequestMode.HEIGHT_FOR_WIDTH

    def get_aspect_ratio(self):
        return self.pb.get_width() / self.pb.get_height()

    def do_draw(self, cr):
        alloc = self.get_allocation()
        pw, ph = self.pb.get_width(), self.pb.get_height()
        aw, ah = float(alloc.width), float(alloc.height)
        r = min(aw/pw, ah/ph)
        cr.scale(r, r)
        Gdk.cairo_set_source_pixbuf(cr, self.pb, 0.0, 0.0)
        cr.paint()
        return False

bin = Gtk.Box(False)
bin.set_orientation(Gtk.Orientation.VERTICAL)

img = ScalableImage("gnome-logo.png")
bin.add(img)

tv = Gtk.TextView()
buf = tv.get_buffer()
buf.set_text("Lorem ipsum dolor sit amet, consectetur adipiscing elit.\
Quas enim kakaw Graeci appellant, vitia malo quam malitias nominare.\
Quod autem satis est, eo quicquid accessit, nimium est; Solum\
praeterea formosum, solum liberum, solum civem, stultost; Erat enim\
Polemonis. Conferam tecum, quam cuique verso rem subicias; Duo Reges:\
constructio interrete. Aufert enim sensus actionemque tollit\
omnem.\n\nQuae cum magnifice primo dici viderentur, considerata minus\
probabantur. In quibus doctissimi illi veteres inesse quiddam caeleste\
et divinum putaverunt. Dolere malum est: in crucem qui agitur, beatus\
esse non potest. Tu vero, inquam, ducas licet, si sequetur; Eademne,\
quae restincta siti? Sint modo partes vitae beatae. Sextilio Rufo, cum\
is rem ad amicos ita deferret, se esse heredem Q. Negat enim summo\
bono afferre incrementum diem. Sin te auctoritas commovebat, nobisne\
omnibus et Platoni ipsi nescio quem illum anteponebas?\n\nIstam\
voluptatem, inquit, Epicurus ignorat? Inde sermone vario sex illa a\
Dipylo stadia confecimus. Quam ob rem tandem, inquit, non satisfacit?\
Duae sunt enim res quoque, ne tu verba solum putes.\n\nComprehensum,\
quod cognitum non habet? Nunc ita separantur, ut disiuncta sint, quo\
nihil potest esse perversius. Quod ea non occurrentia fingunt, vincunt\
Aristonem; Nos commodius agimus.\n\nCerte, nisi voluptatem tanti\
aestimaretis. Roges enim Aristonem, bonane ei videantur haec: vacuitas\
doloris, divitiae, valitudo; Quid ergo aliud intellegetur nisi uti ne\
quae pars naturae neglegatur? Ab hoc autem quaedam non melius quam\
veteres, quaedam omnino relicta. Verum tamen cum de rebus grandioribus\
dicas, ipsae res verba rapiunt; Dolor ergo, id est summum malum,\
metuetur semper, etiamsi non aderit; Etenim nec iustitia nec amicitia\
esse omnino poterunt, nisi ipsae per se expetuntur. Summum ením bonum\
exposuit vacuitatem doloris")
tv.set_wrap_mode(Gtk.WrapMode.WORD)

sw = Gtk.ScrolledWindow()
sw.add(tv)
sw.set_vexpand(True)
bin.add(sw)

assistant = Gtk.Assistant()
n = assistant.append_page(bin)
assistant.set_page_type(bin, Gtk.AssistantPageType.INTRO)
assistant.set_page_title(bin, "Start")
assistant.set_page_complete(bin, True)

label = Gtk.Label("Done!")
assistant.append_page(label)
assistant.set_page_type(label, Gtk.AssistantPageType.CONFIRM)
assistant.set_page_title(label, "End")

assistant.set_current_page(n)

assistant.connect("close", Gtk.main_quit)
assistant.connect("cancel", Gtk.main_quit)
assistant.connect("delete-event", Gtk.main_quit)

assistant.resize(600,800)
assistant.show_all()
Gtk.main()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]