下面是在ubuntu1410執行後樣子,OS版本不要太舊,應該都可執行
已經找到python file使用中文的方式,開頭給字形
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
圖片拉大後可拉小了,要將viewport先加進捲動視窗(如下圖)
多加了檔案列表類別t_filechosser,處理檔選擇器被選取後,把檔案加入TreeView列表中,當TreeView列表被選取時,信號呼叫重新調整image大小後顯示,其實有些可以用Glade來設計,用glade會有些不滿意,乾脆這部份就不用glade,成一個CLASS,日後也可拿來用,譬如音樂播放氣
另外加強image_viewport這類別的功能,能夠保持等比例縮小或放大圖片
程式碼共有4個檔案(一個glade建立的ui檔,3個用Anjuta IDE編輯的py檔)如下
pygtk_foobar_u1410.ui
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<object class="GtkFileFilter" id="filefilter1">
<patterns>
<pattern>*.jpg</pattern>
<pattern>*.png</pattern>
<pattern>*.PNG</pattern>
<pattern>*.JPG</pattern>
</patterns>
</object>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name gchararray1 -->
<column type="gchararray"/>
</columns>
</object>
<object class="GtkWindow" id="window">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">False</property>
<property name="vexpand">False</property>
<property name="title" translatable="yes">圖片檢視器</property>
<property name="window_position">center</property>
<property name="default_width">700</property>
<property name="default_height">502</property>
<property name="gravity">center</property>
<signal name="check-resize" handler="IMAGE_RESIZE" object="viewport1" swapped="no"/>
<signal name="destroy" handler="on_window_destroy" swapped="no"/>
<child>
<object class="GtkPaned" id="paned1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton" id="button6">
<property name="label" translatable="yes"> 選 擇 圖 片 檔 ... </property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="IMAGE_VIEWER" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button3">
<property name="label" translatable="yes">離開</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="SHOW_IMAGE" object="window" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label" translatable="yes">隱藏圖片</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="SHOW" object="label1" swapped="no"/>
<signal name="clicked" handler="SHOW_IMAGE" object="image1" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">4</property>
<property name="label" translatable="yes">訊息</property>
<property name="ellipsize">start</property>
<property name="max_width_chars">0</property>
<attributes>
<attribute name="font-desc" value="<輸入數值> 18"/>
<attribute name="style" value="italic"/>
<attribute name="weight" value="bold"/>
<attribute name="foreground" value="#cccc00000000"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">20</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">顯示圖片</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="yalign">0.44999998807907104</property>
<signal name="clicked" handler="SHOW" object="label1" swapped="no"/>
<signal name="clicked" handler="SHOW_IMAGE" object="image1" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button4">
<property name="label" translatable="yes">縮放</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="SHOW" object="label1" swapped="no"/>
<signal name="clicked" handler="SHOW_TYPE" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button5">
<property name="label" translatable="yes">擴展</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="SHOW" object="label1" swapped="no"/>
<signal name="clicked" handler="SHOW_TYPE" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">7</property>
</packing>
</child>
</object>
<packing>
<property name="resize">False</property>
<property name="shrink">True</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkViewport" id="viewport1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_BUTTON_MOTION_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK</property>
<child>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="stock">gtk-missing-image</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
treeview_filechooser.py
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
# treeview_filechosser.py
#
# Copyright (C) 2015 - root
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
#給頂層視窗window參數,容器add_widget參數,和處理圖片的物件view參數,可加入TreeView到容器dd_widget
#call_resize方法中,參數view物件須提供方法i_image_resize,此方法只是來處理,TreeView選項被選取後會呼叫
#此treeview,提供File_open()來打開檔案圖片,選取後加入treeview的表單
#_type_若是"DELETE",選取file,加入treeview會先清空treeview內容,否則一直加上去
from gi.repository import Gtk, GdkPixbuf, Gdk
import sys,os
from gi.repository.GdkPixbuf import Pixbuf, InterpType
class t_filechosser():
#建構式,用來初始化物件
def __init__(self,add_widget,window,view,_type_,ifile):
#inital data
self._TYPE_=_type_
self.add_tree_w=add_widget
self.window=window
self.image_viewport_new=view
self.file=ifile
#新Treeview,要先有store來存放資料
self.store = Gtk.ListStore(str)
self.tt=Gtk.TreeView(self.store)
#Treeview加入
self.add_tree_w.add(self.tt)
#建立signal connect
self.tt.connect('cursor-changed', self.SHOW_ITEM)
#記得要給TreeViewColumn,否則TreeView無法顯示
column = Gtk.TreeViewColumn("-----檔名-----", Gtk.CellRendererText(), text=0)
column.set_sort_column_id(0)
self.tt.append_column(column)
def File_open(self):
self.dlg = Gtk.FileChooserDialog(
"Select Picture",
self.window,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK) )
self.dlg.show()
print("開啟檔案選擇器")
self.dlg.set_default_response(Gtk.ResponseType.CANCEL)
self.dlg. set_select_multiple(True)
#可用glade加檔案過濾器
#self.dlg.add_filter(self.filefilter1)
#加檔案過濾器'*.jpg','*png','*PNG','*.JPG'
lfilter = Gtk.FileFilter()
lfilter.set_name('Picture')
flist=list(('*.jpg','*png','*PNG','*.JPG'))
for fl in flist:
lfilter.add_pattern(fl)
print(fl)
self.dlg.add_filter(lfilter)
self.dlg.set_filter(lfilter)
#設定filechosserdialog按鈕事件,按OK加入list,否則destroy
response = self.dlg.run()
if response == Gtk.ResponseType.OK:
if self._TYPE_=="DELETE":self.store.clear()
#取得選取file list
lfile=self.dlg.get_filenames()
#print(lfile[0])
#加入treeview list
for x in lfile:
#self.liststore1.append([x])
self.store.append([x])
#self.image_viewport_new.i_image_resize(lfile[0])
self.tt.set_cursor(0)
self.dlg.destroy()
elif response == Gtk.ResponseType.CANCEL:
print("Cancel clicked")
#注意最後要destroy,讓使用者按左上x能關閉
self.dlg.destroy()
#連結信號,設定顯示的樣式
def SHOW_ITEM(self, widget,*event):
try :
sel=self.tt.get_selection()
(model,iter)=sel.get_selected()
self.file=list(model[iter])[0]
#取得image_viewport_new物件的i_image_resize來重設圖片大小
#self.image_viewport_new.i_image_resize(self.file)
self.call_resize()
print(list(model[iter])[0])
except:pass
def call_resize(self):
try :
self.image_viewport_new.i_image_resize(self.file)
except:print("請給一個物件的方法i_image_resize,來處理TreeView選項被選取")
size_image.py
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#image_viewport類別,是用來重設圖片大小
#給一個image參數, viewport參數,i_type參數,產生物件,此物件提供調整圖片大小的i_image_resize方法
#image是顯示該圖片的widget
#viewport是放image的容器
#i_type給任何字串,圖片會調到和viewprt一樣大,若設定"縮放",照圖片等比例調整
#i_image_resize(self,filepath)給圖片filepath,重設圖片大小
#is_viewpot_change(self,widget)給viewport,判定viewport是否改變
#為什要判定viewport是否改變,譬如給check-resize信號用來判斷,當使用者拉大視窗一下,
#連結調整圖片,載入圖片時,會觸發check-resizecheck-resize又會呼叫調整圖片,變成迴圈
from gi.repository import Gtk, GdkPixbuf, Gdk
import sys,os
from gi.repository.GdkPixbuf import Pixbuf, InterpType
class image_viewport():
#建構式,用來初始化物件
def __init__(self,image, viewport,i_type):
#inital data
self.w_size=0
self.h_size=0
self.image = image
self.viewport = viewport
self.i_type=i_type
#定義了一些取得設定物件成員值
def i_get_viewport_h_size(self):
return self.h_size
def i_get_viewport_w_size(self):
return self.w_size
def i_set_show_type(self,i_type):
self.i_type= i_type
def i_get_show_type(self):
return self.i_type
def is_viewpot_change(self,widget):
#目前viewport size
boolean=False
w_size=widget.get_allocation().width
h_size=widget.get_allocation().height
#檢查viewport是否改變,若是回傳值True
if(self.w_size!=w_size or self.h_size!=h_size ):
boolean=True
return boolean
#定義重設視窗的方法
def i_image_resize(self,filepath):
self.h_size=self.viewport.get_allocation().height
self.w_size=self.viewport.get_allocation().width
#從filepath產生圖片buffer
pixbuf = Pixbuf.new_from_file(filepath)
#orange image size
iw=pixbuf.get_width()
ih=pixbuf.get_height()
#參數先轉成float
w,h=change_width_height(self,float(iw),float(ih),float(self.w_size),float(self.h_size))
print("width" ,w)
print("height",h)
#重設圖片buffer寬高
pixbuf = pixbuf.scale_simple(w, h, InterpType.BILINEAR)
#把圖片buffer放到image widget
self.image.set_from_pixbuf(pixbuf)
#定義方法,用來計算圖片新的寬高,並回傳寬和高
def change_width_height(self,ix,iy,vx,vy):
#預設回傳viewport寬和高
width=vx
height=vy
cy=iy/vy
cx=ix/vx
#print(cy)
#print(self.i_type)
#判斷image與viewport比例,顯示若是EXTEND形式,設定新的寬和高
if cx >= cy and self.i_type=="縮放":
try:
#new size
width=ix/cx
height=iy/cx
except:pass
if cy >= cx and self.i_type=="縮放":
try:
#new size
width=ix/cy
height=iy/cy
except:pass
return width,height
#結束def change_width_height end
主程式pygtk_foobar_u1410.py
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# main.py
# Copyright (C) 2015 yplin
#
# pygtk-foobar_u1410 is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pygtk-foobar_u1410 is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see
from gi.repository import Gtk, GdkPixbuf, Gdk
import os, sys ,size_image,treeview_filechooser
import glob
from gi.repository.GdkPixbuf import Pixbuf, InterpType
#Comment the first line and uncomment the second before installing
#or making the tarball (alternatively, use project variables)
UI_FILE = "src/pygtk_foobar_u1410.ui"
#UI_FILE = "/usr/local/share/pygtk_foobar_u1410/ui/pygtk_foobar_u1410.ui"
class GUI:
def __init__(self):
#新建了一個xml-gtk
self.builder = Gtk.Builder()
#把UI_FILE加到gtk,glade產生的xml
self.builder.add_from_file(UI_FILE)
#建立xml信號連結
self.builder.connect_signals(self)
#取得xml UI上所有元件
self.file="src/logo.png"
self.test_w=0
self.test_h=0
self.label=self.builder.get_object('label1')
self.button2=self.builder.get_object('button2')
self.button1=self.builder.get_object('button1')
self.button3=self.builder.get_object('button3')
self.window=self.builder.get_object('window')
self.fixed=self.builder.get_object('fixed1')
self.image=self.builder.get_object('image1')
self.viewport=self.builder.get_object('viewport1')
self.treeview=self.builder.get_object('treeview1')
self.liststore1=self.builder.get_object('liststore1')
self.filefilter1=self.builder.get_object('filefilter1')
self.scrolledwindow1=self.builder.get_object('scrolledwindow1')
self.image.set_from_file(self.file)
#self.dlg=self.builder.get_object('filechooserdialog1')
#初始化
#self.treeview.append_column(column)
#初始化,產生自定義image_viewport ,t_filechosser CLASS
self.image_viewport_new=size_image.image_viewport(self.image,self.viewport,"擴展")
self.t_filechosser=treeview_filechooser.t_filechosser(self.scrolledwindow1,self.window,self.image_viewport_new,"DELETE",self.file)
def on_window_destroy(self, widget, *event):
Gtk.main_quit()
def on_window_destroy1(self, widget, *event):
print("HHHHHHHHHHH")
#button click 連結信號
def SHOW(self, widget, *event):
print("DDDD")
#self.label.set_text(self.button2.get_label())
try:
#get_focus可取得激活對象
bt_active_label=self.window.get_focus().get_label()
#widget是指信號處理對象,用GALADE創建UI時,是為label1
widget.set_text(bt_active_label)
except:pass
#除錯技巧,印出
#重設label位置
#self.fixed.put(self.label, 80, 40)
#button click 連結信號
def SHOW_IMAGE(self, widget, *event):
#取得激活對象按鈕名稱
bt_active_label=self.window.get_focus().get_label()
#根據按鈕名稱,顯示或隱藏圖片
if bt_active_label=='隱藏圖片':widget.hide()
if bt_active_label=='顯示圖片':widget.show()
if bt_active_label=="離開":Gtk.main_quit()
#Window chec-resize連結信號,重設圖片大小
def IMAGE_RESIZE(self, widget, *event):
#目前viewport size
#w_size=self.viewport.get_allocation().width
#h_size=self.viewport.get_allocation().height
#存在記憶體viewport size
#wv=self.image_viewport_new.i_get_viewport_w_size()
#hv=self.image_viewport_new.i_get_viewport_h_size()
#檢查viewport是否改變,重設size,否則成為無窮迴圈
if self.image_viewport_new.is_viewpot_change(widget) :
#print(str(h_size))
#resize方法,來重設大小方式
self.t_filechosser.call_resize()
#連結信號,設定顯示的樣式
def SHOW_TYPE(self, *event):
b_label=self.window.get_focus().get_label()
self.image_viewport_new.i_set_show_type(b_label)
#resize方法,重設大小方式
self.t_filechosser.call_resize()
print(0 > 3)
def IMAGE_VIEWER(self, *event):
self.t_filechosser.File_open()
def main():
app = GUI()
app.window.show_all()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
沒有留言:
張貼留言