суббота, 31 марта 2012 г.

Опыт HTML и CSS



Здравствуйте, сегодня я расскажу о своём личном опыте по изучению html  и css.


   1.  Начало пути.Обучение.

Самая первая проблема при изучение html и css это конечно с чего начать. Все сразу кидаются искать кучу книг или рыться по каким то сайтам и чаще всего это какие-нибудь форумы. Сразу могу сказать если вы человек который очень любит правильность и чистоту, то можете дальше не читать, так как учить наверно html можно вечно особенно старую школу.  Так что не стоит уделять внимания всяким тегам для изменения шрифта и всё такое. Для примера можно решить задачки отсюда. Всё же думаю смотреть на решение совсем не стоит а сделать самим всё это. Задачки дадут неплохую основу чтобы свободно ориентироваться в тегах и быстро в езжать что да как. Как источник знаний можно использовать этот же сайт для просмотра справочной информации по тегам и css.

   2.  Проверка знаний. Закрепляем.

Вторая часть что нужно сделать, для меня она была просто жутко нудной и скучной, может потому что не особо люблю вкладывать много сил в пустое место, а может это просто не по мне. Но нужно найти сайт какой-нибудь и попытаться сверстать его пускай контент будет статический и забит в коде html. Тут ничего не могу посоветовать конкретно, придётся выбрать что то себе по вкусу. Желательно чтобы это был грамотный сайт, чтобы там использовались разные новые теги от html5 например эти входят в состав минимума. Так же желательно чтобы на сайте был контент в две колонки, часто встречается и очень полезно для тренировки.

   3.   Проверяем код. 

Советы по поводу синтаксиса мало, пока что опыта не много. Избавляться от большого количество не нужных class и id. Если имена у классов ваших тегов по типа divdivdivov  или прочая фигня, то лучше назвать его получше или посмотреть повнимательнее, может он вам и не нужен попросту. Так же нужно избавляться от <br>  всяких. Хорошо изучить зачем нужны padding,border и margin  и все их моды.

   4.   Советы бывалых.

Так же дам совет по поиску примеров. Сразу как только увидели тупо код css без картинки с результатом не стоит тратить на него время. Так же смотреть пример и листать скролом до результата тоже не удобно.

Самая важная часть это не тратить время на мелочи связанные с оформлением кнопок какого то вида ссылок или что то из этой серии. Попытайтесь набить в черновом варианте весь контент  сайта. Поверьте мне если будите подгонять одну кнопку по размерам и внешнему виду три часа и потом продолжите работу обнаружите что ваша кнопка сместилась или стала коряво выглядеть, вас это совсем не обрадует и вы потратили те три часа в пустую. Многие надписи старайтесь делать картинками(следите за фоном) всю статичную часть вообще лучше делать картинками, меньше мороки.

   5. Советы по инструментарию.

После того как всё накидали, более менее это выглядит пришло время оформлять по фен-шую. Тут уже кто как любит можно поставить фотошоп для использования линейки, замер размеров между кнопками и прочего. Размеры я пока что подбирал  на глаз,  для цвета использовал CalorMania .
Повторюсь это лично мои выводы, кому то они показаться глупыми или не верными. Советы принимаются, критика удаляется :)

Полезные ссылки:

Генерация css кода для заливки градиентом

воскресенье, 11 декабря 2011 г.

Паттерн "Декоратор" на Python

Паттер "Декоратор" на языке python. Mocha это молочная пена,а не моча :)))))


from abc import ABCMeta,abstractmethod,abstractproperty
class Beverge:
    def __init__(self):
        self.description = 'Unknown'
    def getDescription(self):
        return self.description
    @abstractmethod
    def cost(self):
        pass
class CondimentDecorator(Beverge):
    @abstractmethod
    def getDescription(self):
        pass
class Expresso(Beverge):
    def __init__(self):
        self.description='Expresso'
    def cost(self):
        return 1.99
class HouseBlend(Beverge):
    def __init__(self):
        self.description='HouseBlend'
    def cost(self):
        return 2.99
class Mocha(CondimentDecorator):
    def __init__(self,beverge):
        self.beverge = beverge
    def getDescription(self):
        return self.beverge.getDescription() + ", Mocha"
    def cost(self):
        return self.beverge.cost() + 0.20
class Soy(CondimentDecorator):
    def __init__(self,beverge):
        self.beverge = beverge
    def getDescription(self):
        return self.beverge.getDescription() + ", Soy"
    def cost(self):
        return self.beverge.cost() + 0.87
if __name__ == "__main__":
    b = Mocha(Soy(Mocha(Expresso())))
    print b.getDescription() + " $ " + str(b.cost())

Выходные данные:
Expresso, Mocha, Soy, Mocha $ 3.26

суббота, 10 декабря 2011 г.

Java паттерн "Декоратор"

Рассмотрим небольшой паттерн проектирования "Декоратор". Он юзается по типу плагина для класса. Добавляя к более общему понятию всякие няшные вкусности. Рассмотрим пример на стандартной библе java. Рассмотрим работу со стандартным потоком ввода.
Диаграмма классов


Красным выделен мой класс декоратор который применяет шифрованию к тексту при чтении файла. InputStrean является абстрактным классом,т.к декоратор тоже является его потомком мы можем использовать силу  полиморфизма,но не для общего случая понимая наследования,а именно для приведения типов.
Итак рассмотрим мой класс(чур не придраться к коду писалось всего несколько минут).


public class EncryptedStream extends FilterInputStream {

    public EncryptedStream(InputStream in) {
        super(in);
    }
    @Override
    public int read() throws IOException{
        int c = super.read();
        if (c != -1){
            if ((char)c == 'o'){
                c = (int)'p';
            }
            if ((char)c == 'l'){
                c = (int)'b';
            }
        }
        return c;
    }
    @Override
    public int read(byte[] b,int offset,int len) throws IOException{
        int l = super.read(b, len, len);
        for(int i = offset; i < offset + l ; i++){
            if ((char)b[i] == 'o'){
                b[i] = (byte)'p';
            }
            if ((char)b[i] == 'l'){
                b[i] = (byte)'b';
            }
        }
        return l;
    }   
}
Рассмотрим применение:




public class EncryptedStreamProject {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            // TODO code application logic here
            InputStream file = new EncryptedStream(
                    new BufferedInputStream(
                            new FileInputStream("test.txt")));
            for (int c = 0;c>=0;c = file.read()){
                System.out.print((char)c);
            }
            file.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Не забываем создать файл test.txt.
Входные данные:
Hello world!
Выходные данные:
Hebbp Wprbd!

Успехов :)

четверг, 28 июля 2011 г.

ANDROID сохранение фотографии с камеры (ANDROID saving photos from your camera )

Здравствуйте мальчики и девочки. Сейчас я вам расскажу историю!

Я занимаюсь разработкой игры для ANDROID, и потребовалось сделать фичу богунеугодную. Надо было из нашего приложения фоткать пользователя, сжимать фотографию до размера такого, чтобы пользователь не смог разглядеть на фотографии сколько у него глаз(1 или 2) и сделать эту картинку его аватарой в игре. Притом фича должна позволять выбирать картинку как тока что сделанную с фотика, так и просто выбрав картинку из памяти. Пользователю конечно 5 секунд экономии, программисту -10 000 нейронов. Ну да ладно история, не в этом.
Нашли, как это сделать, была программуля, которая при запуске сразу запускала камеру и при клике по экрану фоткала и сохраняла фотографию.
В манифесте прописываем разрешение использовать камеру из приложения.
< uses-permission android:name="android.permission.CAMERA" > </uses-permission >

Вот и сорцы собственно.

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;

public class CamaraView extends Activity implements SurfaceHolder.Callback, OnClickListener {

static final int FOTO_MODE = 0;
Camera mCamera;
boolean mPreviewRunning = false;
private Context mContext = this;



public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.camaraview);

mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceView.setOnClickListener(this);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}



@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}



Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {

if (imageData != null) {

Intent mIntent = new Intent();

StoreByteImage(mContext, imageData, 100, 58, 58, "ImageName");
mCamera.startPreview();

setResult(FOTO_MODE, mIntent);
finish();
}
}
};



protected void onResume() {

super.onResume();
}



protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}



protected void onStop() {
super.onStop();
}



public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();

}



public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mPreviewRunning) {
mCamera.stopPreview();
}

Camera.Parameters p = mCamera.getParameters();
p.set("orientation", "portrait");
p.setPreviewSize(w, h);
mCamera.setParameters(p);
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException e) {}

mCamera.startPreview();
mPreviewRunning = true;
}



public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}



private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;



public void onClick(View arg0) {
mCamera.takePicture(null, mPictureCallback, mPictureCallback);

}



public static void StoreByteImage(Context mContext, byte[] imageData, int quality, int height, int weight, String expName) {

FileOutputStream fileOutputStream = null;
try{

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 5;

Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0, imageData.length, options);
Bitmap myScaledImage = Bitmap.createScaledBitmap(myImage, height, weight, false);

fileOutputStream = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/" + expName + ".jpg");

BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);

myScaledImage.compress(CompressFormat.JPEG, quality, bos);

bos.flush();
bos.close();
}
catch (IOException e) {}
}
}

Многовато, да? Ну мы радовалась что программуля работает, фоткает и сохраняет. Но вот беда. Привет разработчикам android'a, чтобы вы находились в try и вас выкинуло исключением в космос нахер!!!
Объясняю, почему я так злюсь. Когда мы начали прикручивать вызов этого диалога, по кнопке картинка не сохранялась. Как только мы не изменяли код, откуда тока его не брали. В интернете куча способов и все разные, я считаю это как минус, так и плюс, хотя для нас было это большим минусом, т.к сбивало нас с толку, всё ли верно в коде мы делаем. Потом, прошарив кучу страничек что выдал google, я натолкнулся на строчку, которую надо прописать в манифесте твоего приложения, которая позволяет приложению сохранять или изменять файлы.
< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" / > 

Вот она. Так какого хрена та програмуля работала без этой строчки, если делать это можно лишь с разрешения, то не зависимо главное это окно или вызов диалога. В общем ребятки надеюсь вам это поможет.

среда, 29 июня 2011 г.

Перенос QtCreator проектов

У новичков которые хотят попробовать QtCreator часто возникают проблемы с переносом проектов в другой каталог или на другой компьютер. В следствии чего при сборке возникает проблема связанная с qmake. т.к вся сборка проходит в теневом режиме,т.е пользователь сам не вводит команды для сборки и прописывание путей к исходным файлам,то при переносе проекта все теневые настройки остаются для каталога до переноса
Пример :
Допустим при создании проекта в D:\Programming\qt\project\table. QtCreator автоматически создаст папку для сборки на том же уровне где и папка с исходниками,т.е это будет D:\Programming\qt\project\table-build-desktop например. Теперь мы решим перенести наш проект в другую папку,например D:\Programming\table и стереть все созданные им папки. После запуска *.pro файла и старта компиляции он нам скажет что не может найти папку для сборки и бла-бла-бла. К сожалению QtCreator туповат и не может сам создать папку для сборки проекта,поэтому приходиться там тыкать ему в "лицо" путь до папки для сборки,на скриншоте показано как это можно сделать. И ещё такой нюанс, если есть в пути русские буквы он тоже капризничает,так что не советую .

пятница, 24 июня 2011 г.

PyQt + GoogleAPI


Недавно заинтересовался языком python и решил сваять что-то. Так как я любитель Qt то и сваял gui с их помощью.
Задача была несложной.Ввести свои данные gmail и увидеть список своих документов на https://docs.google.com/.
Вот что получилось для примера:
main.py

from gui import *

if __name__ == '__main__':
import sys

app = QApplication(sys.argv)
window = Dialog()
sys.exit(window.exec_())

gui.py

#coding=windows-1251
from PySide.QtCore import *
from PySide.QtGui import *
import gdata.docs.service


class Dialog(QDialog):
def __init__(self):
super(Dialog,self).__init__()
# кодировка
QTextCodec.setCodecForCStrings(QTextCodec.codecForName("UTF-8"))
# добавляем всякие виджеты
self.setGui()
# конектим слоты
if(self.connect() == False):
print 'Connect do not work!'
def setGui(self):
# добавляем виджеты
self.labelEmail = QLabel('Email',self)
self.labelPassword = QLabel('Password',self)
self.lineEmail = QLineEdit(self)
self.linePassword = QLineEdit(self)
self.linePassword.setEchoMode(QLineEdit.Password)
self.list = QListWidget(self)
self.buttonGet = QPushButton('Get',self)
# создаём лаяут
self.grid = QGridLayout(self)
# кидаем туда виджеты
self.grid.addWidget(self.labelEmail,0,0)
self.grid.addWidget(self.labelPassword,1,0)
self.grid.addWidget(self.lineEmail,0,1)
self.grid.addWidget(self.linePassword,1,1)
self.grid.addWidget(self.list,2,0,1,2)
self.grid.addWidget(self.buttonGet,3,0,1,2)
def connect(self):
flag = False
flag = self.buttonGet.clicked.connect(self.on_buttonGetClicked)
return flag
# получаем список документов на доках хухла и добавляем в таблицу
def on_buttonGetClicked(self):
client = gdata.docs.service.DocsService()
client.ClientLogin(self.lineEmail.text(), self.linePassword.text())
documents_feed = client.GetDocumentListFeed()
for document_entry in documents_feed.entry:
self.list.addItem(document_entry.title.text)

воскресенье, 9 января 2011 г.

Неименованные каналы в windows


/* Программа клиент */
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
#include "string.h"
#include "iostream"
#include "vector"
#define STOP -1 // Завершение цикла
using namespace std;
/*!
* Функция для проверки верности байт
*\param byteFirst - первое количество байт
*\param byteSecond - второе количество байт
*\return - 1 - количество байт совпадает, 0 - количество байт не совпадает
*/
bool checkByte(DWORD & byteFirst,DWORD & byteSecond)
{
if(byteFirst!= byteSecond)
return false;
return true;
}
int main(int argc, char* argv[])
{
// Если есть параметры у клиента(дескриптор на чтеление из канала)
if(argc<1)
{
// Завершение программы
cout << "Arrguments not enter" << endl;
_getch();
return -1;
}
int command = 0;
DWORD byteRead; // количество байт на чтение
DWORD byteNeedRead; // реальное количество прочитанах байт
// перевод аргумента из строковой формы в HANDLE
HANDLE hRead = (HANDLE)atoi(argv[0]);
// количесто байт на чтение
byteRead = sizeof(int);
// цикл до команды завершение цикла(-1)
while(command!=STOP)
{
// чтение данных из канала и проверка на верное считывание
if(ReadFile(hRead,(void*)&command,byteRead,&byteNeedRead,NULL) == FALSE || checkByte(byteRead,byteNeedRead) == false || byteNeedRead == 0)
{
// если даные не считались или считались неполностью
cout << "Fail with read" << endl;
_getch();
return -1;
}
// вывод считанных данныхх
cout << command << endl;
}
_getch();
return 0;
}


/* Программа сервер */
#include "stdafx.h"
#include "winsock2.h"
#include "windows.h"
#include "conio.h"
#include "string.h"
#include "iostream"
#include "vector"
#define STOP -1
using namespace std;
/*!
* Функция для проверки верности байт
*\param byteFirst - первое количество байт
*\param byteSecond - второе количество байт
*\return - 1 - количество байт совпадает, 0 - количество байт не совпадает
*/
bool checkByte(DWORD & byteFirst,DWORD & byteSecond)
{
if(byteFirst!= byteSecond)
return false;
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hWrite; // дескриптор для записи
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE hRead; // дескриптор для чтения
int count = 0; // количество цифр для ввода
int *number; // цифры
wchar_t buffer[10]; // буфер для дискриптора
DWORD writeByte; // количество байт которые запишутся в канал
DWORD needWrite; // количество байт которые нужно записать в канал
SECURITY_ATTRIBUTES attr;
attr.bInheritHandle = TRUE; // наследуемый дескриптор
attr.lpSecurityDescriptor = NULL;
attr.nLength = sizeof(SECURITY_ATTRIBUTES);
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Создание неименновоного канала
if(!CreatePipe(&hRead,&hWrite,&attr,1024))
return -1;
// Перевод дескриптора на чтение в строковую форму
_itow((int)hRead,buffer,10);
// Создание нового процесса
// Параметром командной строки является дескриптор на чтение
if(!CreateProcess(L"child.exe",buffer,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi))
{
// в случае ошибка закрытие дескрипторы на чтение и на запись
CloseHandle(hRead);
CloseHandle(hWrite);
printf( "CreateProcess failed (%d)\n", GetLastError() );
_getch();
return -1;
}
// Ввод количество цифр и самих цифр
cout << "Enter count number: ";
scanf("%d", &count);
number = (int*)calloc(sizeof(int),count);
for(int i = 0 ; i < count; i++)
cin >> number[i];
writeByte = sizeof(int); // количество байт которые будут записываться в канал
// Если произошла запись в канал, записалось нужное количество байт и они записались
if(WriteFile(hWrite,(void*)&count,writeByte,&needWrite,NULL) == FALSE || checkByte(writeByte,needWrite) == false || needWrite ==0)
{
// если была ошибка
cout << "Data was break" << endl;
goto exit;
}
// запись чисел в канал и проверка как и в прошлом комментарии
for(int i = 0 ; i < count ; i++)
if(WriteFile(hWrite,(void*)&number[i],writeByte,&needWrite,NULL) == FALSE || checkByte(writeByte,needWrite) == false || needWrite ==0)
{
cout << "Data was break" << endl;
break;
}
// после отправки всех чисел отправка комманды на завершение,так же с проверкой
count = -1;
if(WriteFile(hWrite,(void*)&count,writeByte,&needWrite,NULL) == FALSE || checkByte(writeByte,needWrite) == false || needWrite ==0)
{
cout << "Data was break" << endl;
goto exit;
}
exit:
// Завершение всех процесов и закрытие программы
free(number);
FlushFileBuffers(hRead);
FlushFileBuffers(hWrite);
CloseHandle(hRead);
CloseHandle(hWrite);
_getch();
return 0;
}