2021年7月29日 星期四

如何在ListBox輸出滑鼠點選順序的序列

ListBox預設只能輸出由上而下輸出所選序列,跟滑鼠點選順序無關。如果要輸出滑鼠點選順序的序列,可參考以下程式碼。

# coding=utf-8
import os, re, sys, clr, json, math, logging

os.chdir(os.path.dirname(__file__))
logging.basicConfig(filename='gui.log', filemode='w', encoding='utf-8', level=logging.DEBUG)
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')

from System import Drawing, Array, ComponentModel, Diagnostics, IO
from System.Windows import Forms
import System.Object as object
import System.String as string
from System.Windows.Forms import DialogResult, OpenFileDialog, SaveFileDialog, FolderBrowserDialog

# ----------------------------------------------------------------------------
try:
image_path = './ANSYS.png'
oDesktop.ClearMessages("", "", 2)
AddWarningMessage('Welcome')
except:
pass


# ----------------------------------------------------------------------------
class MyForm(Forms.Form):
def __init__(self):
self.listBox1 = Forms.ListBox()
self.textBox1 = Forms.TextBox()
self.SuspendLayout()
# listBox1
self.listBox1.FormattingEnabled = True
self.listBox1.ItemHeight = 19
self.listBox1.Items.Add("a")
self.listBox1.Items.Add("b")
self.listBox1.Items.Add("c")
self.listBox1.Items.Add("d")
self.listBox1.Items.Add("e")
self.listBox1.Items.Add("f")
self.listBox1.Items.Add("g")
self.listBox1.Items.Add("h")
self.listBox1.Items.Add("i")
# self.listBox1.SelectedIndex = 0
self.listBox1.Location = Drawing.Point(12, 12)
self.listBox1.Name = "listBox1"
self.listBox1.SelectionMode = Forms.SelectionMode.MultiExtended
self.listBox1.Size = Drawing.Size(331, 422)
self.listBox1.TabIndex = 0
self.listBox1.SelectedIndexChanged += self.listBox1_SelectedIndexChanged

# textBox1
self.textBox1.Location = Drawing.Point(388, 12)
self.textBox1.Multiline = True
self.textBox1.Name = "textBox1"
self.textBox1.Size = Drawing.Size(400, 426)
self.textBox1.TabIndex = 1
# Form1
self.AutoScaleDimensions = Drawing.SizeF(9, 19)
self.AutoScaleMode = Forms.AutoScaleMode.Font
self.ClientSize = Drawing.Size(800, 450)
self.Controls.Add(self.textBox1)
self.Controls.Add(self.listBox1)
self.Name = "Form1"
self.Text = "Form1"
self.ResumeLayout(False)
self.PerformLayout()
self.selected = []

def listBox1_SelectedIndexChanged(self, sender, e):

sel = [i for i in sender.SelectedItems]
if not set(self.selected).issubset(set(sel)):
self.selected = []

for i in self.selected:
sel.remove(i)
self.selected += list(sel)
self.textBox1.Text = str(self.selected)


if __name__ == '__main__':
try:
form = MyForm()
form.ShowDialog()
form = MyForm()
form.Dispose()
# form.Show()
# oDesktop.PauseScript()
except:
logging.exception('ERROR!')



2021年7月24日 星期六

如何在GUI當中直接顯示圖片

在編寫GUI時,如果我們想要在GUI上面加上圖片,又不希望另外附加圖片檔,那可以將圖片轉成base64格式的字串放在Python檔案當中,透過函數呼叫直接導入到PictureBox。

# coding=utf-8
import os, re, sys, clr, json, math, logging
os.chdir(os.path.dirname(__file__))
logging.basicConfig(filename='gui.log', filemode='w', encoding='utf-8', level=logging.DEBUG)
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')

from System import Drawing, Array, ComponentModel, Diagnostics, IO, Convert
from System.Windows import Forms
import System.Object as object
import System.String as string
from System.Windows.Forms import DialogResult, OpenFileDialog ,SaveFileDialog, FolderBrowserDialog
#----------------------------------------------------------------------------
base64_img = '''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
AAAAAAAAAAAAAAAAAAAAAAAH//2Q=='''



#----------------------------------------------------------------------------
class MyForm(Forms.Form):
def __init__(self):
self.pictureBox1 = Forms.PictureBox()
((self.pictureBox1)).BeginInit()
self.SuspendLayout()
# pictureBox1
self.pictureBox1.Location = Drawing.Point(95, 46)
self.pictureBox1.Name = "pictureBox1"
self.pictureBox1.Size = Drawing.Size(589, 337)
self.pictureBox1.TabIndex = 0
self.pictureBox1.TabStop = False
x = Drawing.Image.FromStream(IO.MemoryStream(Convert.FromBase64String(base64_img)))
self.pictureBox1.Image = x
# Form1
self.AutoScaleDimensions = Drawing.SizeF(9, 19)
self.AutoScaleMode = Forms.AutoScaleMode.Font
self.ClientSize = Drawing.Size(800, 450)
self.Controls.Add(self.pictureBox1)
self.Name = "Form1"
self.Text = "Form1"
((self.pictureBox1)).EndInit()
self.ResumeLayout(False)

if __name__ == '__main__':
form = MyForm()
form.ShowDialog()
form = MyForm()
form.Dispose()
AddWarningMessage('Good Bye!')
#form.Show()
#oDesktop.PauseScript()



2021年7月4日 星期日

如何將tech檔案轉成控制檔

在手動匯入GDSII檔案的時候,我們是輸入.tech檔案將層數編號轉成一般的名稱,如圖一。但是在錄製腳本的時候,無法設定.tech檔案。這時候我們可以利用控制檔(.xml)來取代,程式碼如下:

oTool = oDesktop.GetTool("ImportExport")
oTool.ImportGDSII(gds_path, aedb_path, control_path, "")

以下函數可以將.tech檔轉成.xml檔:

def techToControlFile(tech_path, unit='mm'):
result = []
with open(tech_path) as f:
for line in f:
try:
layerID, layer_name, color, elevation, layer_height = line.split()
x = ' <Layer Color="#ff0000" GDSIIVia="false" Name="{}" TargetLayer="{}" Thickness="{}" Type="conductor"/>'.format(
layerID, layer_name, layer_height)
result.append(x)
except:
pass

frame = '''<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<c:Control xmlns:c="http://www.ansys.com/control" schemaVersion="1.0">

<Stackup schemaVersion="1.0">
<Layers LengthUnit="{}">
{}
</Layers>
</Stackup>

<ImportOptions Flatten="true" GDSIIConvertPolygonToCircles="false" ImportDummyNet="true"/>

</c:Control>'''

return frame.format(unit, '\n'.join(result))

(圖一) 手動操作時設定.tech檔來選定匯入的GDS層